diff --git a/.vscode/settings.json b/.vscode/settings.json index d7c1bfc1d1e..0ef2ce67760 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,6 +13,8 @@ }, "files.eol": "\n", "files.insertFinalNewline": true, + "files.trimTrailingWhitespace": true, + "editor.insertSpaces": false, "git.branchProtection": ["master"], "gitlens.advanced.blame.customArguments": ["-w"], "tgstationTestExplorer.project.resultsType": "json", diff --git a/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm b/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm index 61311b3f036..cddd5a08206 100644 --- a/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm +++ b/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm @@ -337,7 +337,7 @@ /area/ruin/powered/golem_ship) "un" = ( /obj/structure/table/wood, -/obj/item/areaeditor/blueprints/golem{ +/obj/item/blueprints/golem{ pixel_y = 3; pixel_x = -2 }, diff --git a/_maps/RandomRuins/SpaceRuins/skyrat/port_tarkon.dmm b/_maps/RandomRuins/SpaceRuins/skyrat/port_tarkon.dmm index af475c05f23..5373695f714 100644 --- a/_maps/RandomRuins/SpaceRuins/skyrat/port_tarkon.dmm +++ b/_maps/RandomRuins/SpaceRuins/skyrat/port_tarkon.dmm @@ -5070,7 +5070,7 @@ /area/ruin/space/has_grav/port_tarkon/mining) "Jg" = ( /obj/structure/safe/floor, -/obj/item/areaeditor/blueprints/tarkon, +/obj/item/blueprints/tarkon, /obj/item/circuitboard/machine/bluespace_miner, /turf/open/floor/iron, /area/ruin/space/has_grav/port_tarkon/power1) @@ -7313,7 +7313,7 @@ /obj/effect/turf_decal/tile/purple/half{ dir = 1 }, -/obj/item/areaeditor/blueprints/slime, +/obj/item/blueprints/slime, /obj/item/slime_extract/grey, /obj/item/slime_extract/grey, /obj/item/slime_extract/grey, diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index d9fb22def8f..eec9705fcf4 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -2799,6 +2799,12 @@ }, /turf/open/floor/circuit/green, /area/station/science/robotics/mechbay) +"boT" = ( +/obj/effect/turf_decal/bot, +/obj/machinery/light/cold/dim/directional/west, +/obj/machinery/vending/wardrobe/engi_wardrobe, +/turf/open/floor/iron, +/area/station/engineering/main) "boW" = ( /obj/structure/table/glass, /obj/machinery/status_display/ai/directional/south, @@ -10007,18 +10013,6 @@ /obj/effect/turf_decal/siding/wood, /turf/open/floor/wood/tile, /area/station/science/lower) -"erJ" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/structure/table/greyscale, -/obj/item/folder/yellow{ - pixel_x = 4; - pixel_y = 4 - }, -/obj/item/clothing/glasses/meson, -/turf/open/floor/iron/grimy, -/area/station/engineering/main) "erK" = ( /obj/structure/cable, /obj/effect/turf_decal/siding/thinplating_new, @@ -11513,13 +11507,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/hallway/primary/fore) -"eWf" = ( -/obj/structure/closet/cardboard, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/turf/open/floor/iron/grimy, -/area/station/engineering/main) "eWj" = ( /obj/machinery/atmospherics/components/unary/thermomachine/heater/on{ dir = 4; @@ -11999,17 +11986,6 @@ /obj/machinery/light_switch/directional/west, /turf/open/floor/iron/cafeteria, /area/station/service/cafeteria) -"fhX" = ( -/obj/structure/table/greyscale, -/obj/item/folder/yellow{ - pixel_x = 2; - pixel_y = 4 - }, -/obj/item/pen{ - pixel_x = -4 - }, -/turf/open/floor/iron/grimy, -/area/station/engineering/main) "fib" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -31165,6 +31141,18 @@ }, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) +"lwl" = ( +/obj/effect/gibspawner/human, +/obj/structure/table/optable{ + desc = "A cold, hard place for your final rest."; + name = "Morgue Slab" + }, +/mob/living/carbon/human/species/monkey/humand_legged{ + name = "Charles"; + real_name = "Charles" + }, +/turf/open/floor/iron/white/diagonal, +/area/station/maintenance/department/science/xenobiology) "lwn" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/door/airlock/hatch, @@ -33051,6 +33039,14 @@ }, /turf/open/floor/iron, /area/station/cargo/storage) +"lWK" = ( +/obj/structure/closet/cardboard, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/item/airlock_painter, +/turf/open/floor/iron/grimy, +/area/station/engineering/main) "lWQ" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/ticket_machine/directional/north, @@ -36959,31 +36955,6 @@ /obj/effect/mapping_helpers/airlock/access/all/security/general, /turf/open/floor/iron/textured_half, /area/station/security) -"nki" = ( -/obj/structure/rack, -/obj/item/airlock_painter, -/obj/item/lightreplacer{ - pixel_y = 7 - }, -/obj/item/clothing/head/utility/hardhat/welding{ - pixel_x = -4; - pixel_y = -3 - }, -/obj/item/clothing/head/utility/hardhat/welding{ - pixel_x = -4 - }, -/obj/item/clothing/head/utility/hardhat/welding{ - pixel_x = -4; - pixel_y = 3 - }, -/obj/effect/turf_decal/bot, -/obj/machinery/light/cold/dim/directional/west, -/obj/item/grenade/chem_grenade/smart_metal_foam{ - pixel_x = 9; - pixel_y = 5 - }, -/turf/open/floor/iron, -/area/station/engineering/main) "nkl" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -45700,10 +45671,6 @@ }, /turf/open/floor/iron/dark/side, /area/station/science/xenobiology) -"pRb" = ( -/obj/item/computer_disk/virus/mime, -/turf/closed/mineral/random/stationside, -/area/space/nearstation) "pRe" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/table/wood, @@ -60444,18 +60411,6 @@ /obj/effect/spawner/random/maintenance, /turf/open/floor/iron, /area/station/security/execution/transfer) -"tUa" = ( -/obj/effect/gibspawner/human, -/obj/structure/table/optable{ - desc = "A cold, hard place for your final rest."; - name = "Morgue Slab" - }, -/mob/living/carbon/human/species/monkey/humand_legged{ - name = "Charles"; - real_name = "Charles" - }, -/turf/open/floor/iron/white/diagonal, -/area/station/maintenance/department/science/xenobiology) "tUc" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -68928,6 +68883,17 @@ }, /turf/open/space/basic, /area/station/engineering/atmos/space_catwalk) +"wlW" = ( +/obj/structure/table/greyscale, +/obj/item/lightreplacer{ + pixel_y = 7 + }, +/obj/item/lightreplacer{ + pixel_y = 2; + pixel_x = -2 + }, +/turf/open/floor/iron/grimy, +/area/station/engineering/main) "wmd" = ( /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible, /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible/layer2{ @@ -70351,8 +70317,8 @@ /turf/open/floor/iron/white, /area/station/medical/medbay/central) "wHO" = ( -/obj/structure/dresser, /obj/structure/sign/poster/official/random/directional/north, +/obj/structure/closet/crate/wooden/toy, /turf/open/floor/wood/parquet, /area/station/service/greenroom) "wHP" = ( @@ -74918,6 +74884,22 @@ }, /turf/open/floor/plating, /area/station/service/abandoned_gambling_den/gaming) +"xMU" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/structure/table/greyscale, +/obj/item/folder/yellow{ + pixel_x = 4; + pixel_y = 4 + }, +/obj/item/clothing/glasses/meson, +/obj/item/grenade/chem_grenade/smart_metal_foam{ + pixel_x = -8; + pixel_y = 14 + }, +/turf/open/floor/iron/grimy, +/area/station/engineering/main) "xMY" = ( /turf/closed/wall/r_wall, /area/station/command/teleporter) @@ -88018,7 +88000,7 @@ aJq aJq aJq aJq -pRb +aJq dDB dDB dDB @@ -88275,7 +88257,7 @@ aJq aJq aJq aJq -pRb +aJq aJq aJq aJq @@ -88532,7 +88514,7 @@ aJq aJq aJq aJq -pRb +aJq aJq aJq aJq @@ -92010,7 +91992,7 @@ dgV sHH rQi rPV -nki +boT uOk nmH sHO @@ -92275,7 +92257,7 @@ dgm wIu oHO sDo -fhX +wlW lsd jJu kya @@ -92786,11 +92768,11 @@ rmM btV lMl ayR -erJ +xMU vDg euP all -eWf +lWK eIx kWg bNq @@ -113439,7 +113421,7 @@ dDB blb dDB ldq -tUa +lwl vXn ldq ldq diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index e81e9481cf7..e66eb438644 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -562,16 +562,6 @@ /obj/structure/chair/stool/directional/east, /turf/open/floor/iron, /area/station/commons/dorms) -"akG" = ( -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 5 - }, -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/obj/structure/tank_holder/extinguisher, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) "akK" = ( /obj/effect/turf_decal/siding/wood{ dir = 1 @@ -4069,15 +4059,6 @@ }, /turf/open/floor/plating/snowed/icemoon, /area/icemoon/surface/outdoors/nospawn) -"bmZ" = ( -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 8 - }, -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) "bna" = ( /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ @@ -4507,13 +4488,6 @@ /obj/effect/decal/cleanable/cobweb/cobweb2, /turf/open/floor/iron/dark, /area/station/maintenance/port/greater) -"bsR" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/landmark/event_spawn, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) "bta" = ( /obj/structure/chair/sofa/bench/right{ dir = 8 @@ -5474,6 +5448,17 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) +"bFw" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/table, +/obj/item/pen{ + pixel_x = -5 + }, +/obj/item/paper_bin, +/turf/open/floor/plating, +/area/station/hallway/secondary/service) "bFS" = ( /obj/item/crowbar/red, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -5682,6 +5667,15 @@ /obj/effect/turf_decal/tile/blue/half/contrasted, /turf/open/floor/iron, /area/station/command/bridge) +"bIQ" = ( +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "bIU" = ( /obj/structure/table, /obj/item/stack/sheet/glass/fifty, @@ -5756,6 +5750,37 @@ /obj/machinery/light/directional/south, /turf/open/floor/iron, /area/mine/laborcamp) +"bJy" = ( +/obj/machinery/button/flasher{ + id = "hopflash"; + pixel_x = 8; + pixel_y = -32 + }, +/obj/machinery/button/door/directional/south{ + id = "hopqueue"; + name = "Queue Shutters Control"; + pixel_x = -8; + req_access = list("hop") + }, +/obj/machinery/button/door/directional/south{ + id = "hop"; + name = "Privacy Shutters Control"; + pixel_x = 8; + req_access = list("hop") + }, +/obj/machinery/button/ticket_machine{ + pixel_x = -8; + pixel_y = -32 + }, +/obj/effect/turf_decal/tile/blue/anticorner/contrasted{ + dir = 8 + }, +/obj/machinery/modular_computer/preset/id{ + dir = 1 + }, +/obj/item/paper/fluff/ids_for_dummies, +/turf/open/floor/iron, +/area/station/command/heads_quarters/hop) "bJA" = ( /obj/effect/turf_decal/siding/wood{ dir = 1 @@ -7593,17 +7618,6 @@ "clq" = ( /turf/open/floor/iron/dark, /area/station/security/processing) -"clr" = ( -/obj/machinery/power/smes{ - capacity = 1.8e+008; - charge = 2e+005 - }, -/obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/effect/decal/cleanable/dirt, -/obj/structure/cable, -/obj/effect/turf_decal/stripes/box, -/turf/open/floor/iron/dark/textured_large, -/area/station/maintenance/disposal/incinerator) "clz" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line{ @@ -8029,6 +8043,17 @@ /obj/item/radio/intercom/directional/east, /turf/open/floor/iron/white, /area/station/science/genetics) +"crH" = ( +/obj/effect/turf_decal/tile/blue/half/contrasted{ + dir = 8 + }, +/obj/machinery/light/small/directional/west, +/obj/machinery/requests_console/directional/west, +/obj/effect/mapping_helpers/requests_console/assistance, +/obj/effect/mapping_helpers/requests_console/announcement, +/obj/effect/mapping_helpers/requests_console/information, +/turf/open/floor/iron, +/area/station/command/heads_quarters/hop) "crS" = ( /obj/machinery/vending/wardrobe/law_wardrobe, /turf/open/floor/wood, @@ -8154,6 +8179,12 @@ /obj/structure/tank_holder/anesthetic, /turf/open/floor/iron/dark, /area/station/science/robotics/lab) +"cua" = ( +/obj/machinery/button/photobooth{ + pixel_y = -26 + }, +/turf/open/floor/iron, +/area/station/command/heads_quarters/hop) "cuc" = ( /obj/effect/turf_decal/siding/thinplating_new, /turf/open/floor/iron, @@ -8528,6 +8559,11 @@ /obj/machinery/light/small/directional/south, /turf/open/floor/plating, /area/station/ai_monitored/turret_protected/aisat_interior) +"czl" = ( +/obj/effect/turf_decal/tile/brown/fourcorners, +/obj/machinery/modular_computer/preset/cargochat/engineering, +/turf/open/floor/iron/dark, +/area/station/engineering/lobby) "czm" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -9857,6 +9893,13 @@ initial_gas_mix = "ICEMOON_ATMOS" }, /area/icemoon/underground/explored) +"cSm" = ( +/obj/machinery/mineral/processing_unit/gulag{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/mine/laborcamp) "cSu" = ( /obj/structure/disposalpipe/segment{ dir = 10 @@ -12609,7 +12652,7 @@ dir = 8 }, /turf/open/floor/engine, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "dJx" = ( /obj/structure/cable, /obj/effect/spawner/structure/window/reinforced, @@ -12852,16 +12895,6 @@ }, /turf/open/floor/iron, /area/station/security/brig/upper) -"dNv" = ( -/obj/machinery/modular_computer/preset/cargochat/security{ - dir = 4 - }, -/obj/machinery/power/apc/auto_name/directional/north, -/obj/structure/cable, -/obj/machinery/light/directional/west, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron/dark/textured, -/area/station/security/office) "dNw" = ( /obj/structure/chair/office{ dir = 8 @@ -13269,6 +13302,18 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/commons/locker) +"dVc" = ( +/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/warning{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "dVq" = ( /obj/machinery/space_heater, /obj/structure/sign/poster/random/directional/east, @@ -13891,9 +13936,6 @@ /obj/structure/cable, /turf/open/floor/iron/white, /area/station/science/xenobiology) -"egf" = ( -/turf/closed/wall/r_wall, -/area/station/science/ordnance/burnchamber) "egj" = ( /obj/structure/rack, /obj/machinery/light/small/directional/north, @@ -15068,6 +15110,18 @@ /obj/item/poster/random_official, /turf/open/floor/plating, /area/station/maintenance/port/fore) +"ezs" = ( +/obj/item/radio/intercom/directional/north, +/obj/effect/turf_decal/tile/red/anticorner{ + dir = 8 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_corner{ + dir = 4 + }, +/area/station/security/office) "ezu" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -15364,6 +15418,18 @@ }, /turf/open/floor/engine, /area/station/engineering/supermatter/room) +"eDH" = ( +/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/warning{ + dir = 4 + }, +/obj/structure/disposalpipe/junction{ + dir = 1 + }, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "eDM" = ( /obj/machinery/door/airlock/command/glass{ name = "Head of Security" @@ -16298,18 +16364,6 @@ /obj/machinery/light/small/directional/north, /turf/open/floor/iron/dark, /area/station/security/execution/education) -"eUH" = ( -/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/warning{ - dir = 4 - }, -/obj/structure/disposalpipe/junction{ - dir = 1 - }, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) "eUI" = ( /obj/machinery/space_heater, /turf/open/floor/plating, @@ -16552,16 +16606,14 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white, /area/station/medical/medbay/central) -"eYz" = ( -/obj/machinery/mineral/processing_unit{ - dir = 1 - }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, -/area/mine/laborcamp) "eYC" = ( /turf/open/floor/iron/smooth, /area/mine/laborcamp/security) +"eYH" = ( +/obj/machinery/power/smes/full, +/obj/structure/cable, +/turf/open/floor/circuit, +/area/station/ai_monitored/turret_protected/ai) "eYL" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/closed/wall, @@ -17877,6 +17929,19 @@ /obj/machinery/light_switch/directional/west, /turf/open/floor/iron, /area/station/cargo/miningdock) +"fvA" = ( +/obj/machinery/computer/security/telescreen/entertainment/directional/north, +/obj/effect/turf_decal/siding/yellow/corner{ + dir = 4 + }, +/obj/structure/table, +/obj/machinery/fax{ + fax_name = "Engineering Lobby"; + name = "Engineering Lobby Fax Machine" + }, +/obj/effect/turf_decal/tile/brown/fourcorners, +/turf/open/floor/iron/dark, +/area/station/engineering/lobby) "fvK" = ( /obj/structure/rack, /obj/item/storage/box/petridish, @@ -18453,15 +18518,6 @@ }, /turf/open/floor/iron, /area/mine/laborcamp/security) -"fEY" = ( -/obj/machinery/modular_computer/preset/cargochat/medical{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/brown/filled/end{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/medical/medbay/aft) "fEZ" = ( /obj/effect/spawner/structure/window, /turf/open/floor/plating, @@ -19266,7 +19322,7 @@ "fSG" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/closed/wall/r_wall, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "fTb" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -20385,18 +20441,6 @@ "gka" = ( /turf/closed/wall/r_wall, /area/station/engineering/supermatter/room) -"gkf" = ( -/obj/structure/window/reinforced/spawner/directional/west, -/obj/machinery/disposal/bin{ - desc = "A pneumatic waste disposal unit. This one leads to the morgue."; - name = "corpse disposal" - }, -/obj/structure/disposalpipe/trunk{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue/fourcorners, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) "gko" = ( /obj/machinery/conveyor{ dir = 8; @@ -20659,17 +20703,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold/yellow/visible, /turf/open/floor/iron, /area/station/engineering/atmos) -"gnA" = ( -/obj/effect/turf_decal/tile/blue/half/contrasted{ - dir = 8 - }, -/obj/machinery/light/small/directional/west, -/obj/machinery/requests_console/directional/west, -/obj/effect/mapping_helpers/requests_console/assistance, -/obj/effect/mapping_helpers/requests_console/announcement, -/obj/effect/mapping_helpers/requests_console/information, -/turf/open/floor/iron, -/area/station/command/heads_quarters/hop) "gnL" = ( /obj/structure/closet/bombcloset/security, /turf/open/floor/iron/smooth, @@ -20936,6 +20969,10 @@ }, /turf/open/floor/iron, /area/station/security/prison/visit) +"grY" = ( +/obj/structure/gulag_vent/ice, +/turf/open/misc/asteroid/snow/icemoon, +/area/icemoon/underground/explored) "gsk" = ( /obj/structure/reflector/single/anchored{ dir = 5 @@ -22526,11 +22563,6 @@ /obj/machinery/light/directional/west, /turf/open/floor/plating, /area/station/cargo/storage) -"gTf" = ( -/obj/effect/turf_decal/tile/brown/fourcorners, -/obj/machinery/photocopier, -/turf/open/floor/iron/dark, -/area/station/engineering/lobby) "gTi" = ( /obj/machinery/door/airlock/medical/glass{ name = "Medbay Chemistry Access" @@ -22742,7 +22774,7 @@ "gWZ" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/monitored/ordnance_burn_chamber_input, /turf/open/floor/engine/vacuum, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "gXe" = ( /obj/effect/turf_decal/siding/white{ dir = 4 @@ -22875,11 +22907,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"gYP" = ( -/obj/machinery/power/smes/full, -/obj/structure/cable, -/turf/open/floor/circuit/telecomms/mainframe, -/area/station/tcommsat/server) "gZa" = ( /obj/structure/sign/nanotrasen{ pixel_x = -32 @@ -23163,6 +23190,14 @@ /obj/effect/mapping_helpers/airlock/access/all/command/general, /turf/open/floor/plating, /area/station/engineering/storage/tech) +"hdn" = ( +/obj/structure/cable, +/obj/effect/turf_decal/tile/red/half/contrasted{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark/textured, +/area/station/security/office) "hdp" = ( /obj/effect/turf_decal/stripes/asteroid/line{ dir = 10 @@ -23317,15 +23352,6 @@ }, /turf/open/floor/iron/showroomfloor, /area/station/security/prison/mess) -"hfw" = ( -/obj/structure/cable, -/obj/machinery/power/smes/full, -/obj/machinery/camera/directional/south{ - c_tag = "Labor Camp Utilities"; - network = list("labor") - }, -/turf/open/floor/iron/smooth, -/area/mine/laborcamp/security) "hfA" = ( /obj/structure/window/reinforced/spawner/directional/north{ pixel_y = 2 @@ -23428,6 +23454,13 @@ dir = 4 }, /area/station/command/gateway) +"hhP" = ( +/obj/machinery/newscaster/directional/south, +/obj/item/kirbyplants/random, +/turf/open/floor/iron/white/side{ + dir = 5 + }, +/area/station/science/lab) "hhT" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/turf_decal/trimline/yellow/filled/line{ @@ -23454,19 +23487,6 @@ /obj/structure/reagent_dispensers/fueltank, /turf/open/floor/plating, /area/station/maintenance/aft/greater) -"hio" = ( -/obj/machinery/computer/security/telescreen/entertainment/directional/north, -/obj/effect/turf_decal/siding/yellow/corner{ - dir = 4 - }, -/obj/structure/table, -/obj/machinery/fax{ - fax_name = "Engineering Lobby"; - name = "Engineering Lobby Fax Machine" - }, -/obj/effect/turf_decal/tile/brown/fourcorners, -/turf/open/floor/iron/dark, -/area/station/engineering/lobby) "hjh" = ( /obj/machinery/computer/records/security{ dir = 4 @@ -23540,6 +23560,21 @@ }, /turf/open/floor/plating, /area/station/medical/virology) +"hjX" = ( +/obj/machinery/requests_console/directional/north{ + department = "Security"; + name = "Security Requests Console" + }, +/obj/effect/mapping_helpers/requests_console/information, +/obj/effect/mapping_helpers/requests_console/assistance, +/obj/effect/turf_decal/tile/red/anticorner, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/turf/open/floor/iron/dark/textured_corner{ + dir = 1 + }, +/area/station/security/office) "hkd" = ( /obj/structure/cable, /obj/machinery/light/small/directional/west, @@ -23803,16 +23838,6 @@ }, /turf/open/floor/iron, /area/station/commons/dorms/laundry) -"hpc" = ( -/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/tile/red/half/contrasted{ - dir = 4 - }, -/obj/item/kirbyplants/random, -/turf/open/floor/iron/dark/textured, -/area/station/security/office) "hpd" = ( /turf/open/floor/plating, /area/station/engineering/engine_smes) @@ -24914,18 +24939,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/command/teleporter) -"hGj" = ( -/obj/item/radio/intercom/directional/north, -/obj/effect/turf_decal/tile/red/anticorner{ - dir = 8 - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 4 - }, -/turf/open/floor/iron/dark/textured_corner{ - dir = 4 - }, -/area/station/security/office) "hGs" = ( /obj/structure/lattice/catwalk, /obj/structure/railing{ @@ -25050,10 +25063,6 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/maintenance, /turf/open/floor/plating, /area/station/maintenance/port/aft) -"hIK" = ( -/mob/living/basic/slime, -/turf/open/floor/engine, -/area/station/science/xenobiology) "hIN" = ( /obj/machinery/light/small/directional/west, /turf/open/floor/iron/dark, @@ -25146,7 +25155,7 @@ dir = 4 }, /turf/open/floor/engine, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "hKr" = ( /obj/structure/table/glass, /obj/item/book/manual/wiki/infections{ @@ -26008,12 +26017,6 @@ }, /turf/open/floor/plating/snowed/icemoon, /area/icemoon/underground/explored) -"hYW" = ( -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/hallway/primary/central) "hZe" = ( /obj/effect/turf_decal/trimline/yellow/warning{ dir = 1 @@ -26040,7 +26043,7 @@ "iao" = ( /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible, /turf/closed/wall/r_wall, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "iar" = ( /obj/structure/cable, /obj/machinery/door/poddoor/preopen{ @@ -26070,15 +26073,6 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/iron, /area/station/cargo/storage) -"iaS" = ( -/obj/effect/turf_decal/tile/blue/half/contrasted{ - dir = 8 - }, -/obj/structure/chair/office{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/command/heads_quarters/hop) "iaT" = ( /obj/effect/spawner/random/trash/mess, /turf/open/floor/plating, @@ -26654,17 +26648,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/maintenance/starboard/fore) -"ijf" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/box/white{ - color = "#52B4E9" - }, -/obj/machinery/holopad, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) "iji" = ( /obj/structure/table, /obj/item/multitool/circuit{ @@ -26947,7 +26930,7 @@ "inb" = ( /obj/machinery/door/poddoor/incinerator_ordmix, /turf/open/floor/engine/vacuum, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "inh" = ( /obj/structure/stairs/west, /obj/structure/railing, @@ -27450,18 +27433,6 @@ }, /turf/open/floor/iron/cafeteria, /area/station/commons/dorms/laundry) -"iuK" = ( -/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{ - dir = 8 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) "iuS" = ( /obj/machinery/airalarm/directional/north, /turf/open/floor/glass/reinforced, @@ -27698,7 +27669,7 @@ dir = 8 }, /turf/open/floor/engine, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "izn" = ( /obj/effect/spawner/random/decoration/generic, /turf/open/floor/plating, @@ -31798,6 +31769,16 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/fore) +"jOS" = ( +/obj/machinery/airalarm/directional/north, +/obj/structure/table, +/obj/machinery/fax{ + fax_name = "Security Office"; + name = "Security Office Fax Machine" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark/textured, +/area/station/security/office) "jOY" = ( /obj/effect/turf_decal/stripes/line, /obj/structure/reagent_dispensers/plumbed{ @@ -32604,16 +32585,6 @@ }, /turf/open/floor/iron, /area/mine/laborcamp) -"kbz" = ( -/obj/machinery/airalarm/directional/north, -/obj/structure/table, -/obj/machinery/fax{ - fax_name = "Security Office"; - name = "Security Office Fax Machine" - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/dark/textured, -/area/station/security/office) "kbJ" = ( /obj/machinery/field/generator, /turf/open/floor/plating, @@ -32861,7 +32832,7 @@ /area/station/maintenance/port/fore) "keV" = ( /turf/open/floor/engine/vacuum, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "keX" = ( /obj/structure/table, /obj/item/stack/cable_coil{ @@ -33094,15 +33065,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/construction) -"khv" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) "khy" = ( /obj/structure/rack, /obj/item/wrench, @@ -34601,6 +34563,11 @@ }, /turf/open/floor/iron/dark, /area/station/science/breakroom) +"kCG" = ( +/obj/effect/turf_decal/tile/brown/fourcorners, +/obj/machinery/photocopier, +/turf/open/floor/iron/dark, +/area/station/engineering/lobby) "kCH" = ( /obj/machinery/door/airlock/security/glass{ name = "Labor Camp Airlock" @@ -35849,6 +35816,15 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron, /area/station/engineering/lobby) +"kVS" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "kWa" = ( /obj/structure/fireplace, /turf/open/floor/plating, @@ -38325,6 +38301,16 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) +"lIt" = ( +/obj/machinery/modular_computer/preset/cargochat/security{ + dir = 4 + }, +/obj/machinery/power/apc/auto_name/directional/north, +/obj/structure/cable, +/obj/machinery/light/directional/west, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark/textured, +/area/station/security/office) "lIy" = ( /obj/structure/table, /obj/effect/turf_decal/tile/red/anticorner/contrasted{ @@ -39224,19 +39210,6 @@ }, /turf/open/lava/plasma/ice_moon, /area/icemoon/underground/explored) -"lWS" = ( -/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/warning{ - dir = 8 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable, -/obj/structure/disposalpipe/segment, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) "lXi" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -40253,6 +40226,18 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/command/bridge) +"mpR" = ( +/obj/structure/window/reinforced/spawner/directional/west, +/obj/machinery/disposal/bin{ + desc = "A pneumatic waste disposal unit. This one leads to the morgue."; + name = "corpse disposal" + }, +/obj/structure/disposalpipe/trunk{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue/fourcorners, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "mpU" = ( /obj/effect/spawner/structure/window, /turf/open/floor/plating, @@ -41354,7 +41339,7 @@ /obj/effect/mapping_helpers/airlock/locked, /obj/effect/mapping_helpers/airlock/access/all/science/ordnance, /turf/open/floor/engine/vacuum, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "mIE" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -41534,11 +41519,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) -"mMf" = ( -/obj/machinery/firealarm/directional/east, -/obj/structure/filingcabinet, -/turf/open/floor/iron/dark/textured, -/area/station/security/office) "mMk" = ( /obj/machinery/telecomms/message_server/preset, /turf/open/floor/iron/dark/telecomms, @@ -41664,6 +41644,13 @@ /obj/effect/turf_decal/tile/blue/half/contrasted, /turf/open/floor/iron, /area/station/command/bridge) +"mOM" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/landmark/event_spawn, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "mPh" = ( /obj/structure/rack, /obj/item/crowbar, @@ -42207,7 +42194,7 @@ "mYd" = ( /obj/machinery/air_sensor/ordnance_burn_chamber, /turf/open/floor/engine/vacuum, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "mYh" = ( /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/ai) @@ -42467,6 +42454,16 @@ /obj/item/radio/intercom/directional/west, /turf/open/floor/carpet/royalblue, /area/station/command/heads_quarters/hos) +"nbw" = ( +/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/tile/red/half/contrasted{ + dir = 4 + }, +/obj/item/kirbyplants/random, +/turf/open/floor/iron/dark/textured, +/area/station/security/office) "nbC" = ( /obj/machinery/smartfridge/chemistry/preloaded, /obj/machinery/door/firedoor, @@ -42798,6 +42795,12 @@ dir = 1 }, /area/station/hallway/secondary/exit/departure_lounge) +"nfD" = ( +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 4 + }, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "nfG" = ( /obj/structure/marker_beacon/burgundy{ name = "landing marker" @@ -43576,15 +43579,6 @@ /obj/effect/turf_decal/stripes/box, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) -"nqt" = ( -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) "nqv" = ( /obj/structure/fence{ dir = 4 @@ -44399,7 +44393,7 @@ "nBV" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on, /turf/open/floor/engine/vacuum, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "nCa" = ( /obj/structure/rack, /obj/item/pickaxe, @@ -45816,9 +45810,6 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron/dark, /area/station/security/prison/visit) -"nYm" = ( -/turf/open/floor/iron/dark, -/area/station/engineering/lobby) "nYn" = ( /obj/structure/closet/secure_closet/personal/cabinet, /turf/open/floor/carpet, @@ -48893,18 +48884,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) -"oTE" = ( -/obj/structure/cable, -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 1 - }, -/obj/machinery/power/apc/auto_name/directional/north, -/obj/item/kirbyplants/random, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) "oTM" = ( /obj/item/flashlight/lantern, /obj/structure/table/wood, @@ -51133,6 +51112,17 @@ "pBE" = ( /turf/closed/wall, /area/station/cargo/bitrunning/den) +"pBI" = ( +/obj/machinery/power/smes{ + capacity = 1.8e+008; + charge = 2e+005 + }, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable, +/obj/effect/turf_decal/stripes/box, +/turf/open/floor/iron/dark/textured_large, +/area/station/maintenance/disposal/incinerator) "pBN" = ( /obj/structure/flora/tree/jungle/small/style_random, /turf/open/floor/grass, @@ -51159,6 +51149,11 @@ }, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"pCE" = ( +/obj/machinery/firealarm/directional/east, +/obj/structure/filingcabinet, +/turf/open/floor/iron/dark/textured, +/area/station/security/office) "pCI" = ( /obj/effect/turf_decal/tile/red{ dir = 8 @@ -54068,6 +54063,17 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron, /area/station/commons/dorms) +"qxu" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/box/white{ + color = "#52B4E9" + }, +/obj/machinery/holopad, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "qxv" = ( /obj/machinery/disposal/bin{ desc = "A pneumatic waste disposal unit. This one leads to the frozen exterior of the moon."; @@ -54316,12 +54322,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/starboard/upper) -"qCH" = ( -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 4 - }, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) "qCI" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -54656,16 +54656,6 @@ /obj/effect/turf_decal/bot_white, /turf/open/floor/iron/checker, /area/station/commons/storage/emergency/port) -"qHa" = ( -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 1 - }, -/obj/machinery/status_display/evac/directional/north, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) "qHg" = ( /obj/structure/transit_tube/curved/flipped{ dir = 1 @@ -54914,13 +54904,6 @@ }, /turf/open/floor/iron/dark/smooth_large, /area/station/hallway/secondary/entry) -"qKN" = ( -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 4 - }, -/obj/structure/extinguisher_cabinet/directional/east, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) "qKQ" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, @@ -55319,6 +55302,10 @@ /obj/machinery/door/window/left/directional/north, /turf/open/floor/iron, /area/station/science/ordnance/testlab) +"qQb" = ( +/obj/machinery/photobooth, +/turf/open/floor/iron, +/area/station/hallway/primary/central) "qQf" = ( /turf/closed/wall, /area/station/maintenance/fore/lesser) @@ -56973,6 +56960,18 @@ dir = 1 }, /area/station/science/explab) +"rqd" = ( +/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{ + dir = 8 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "rqi" = ( /obj/item/crowbar{ pixel_y = 3 @@ -58931,6 +58930,16 @@ }, /turf/open/floor/iron/dark, /area/station/engineering/atmos/hfr_room) +"rWR" = ( +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 1 + }, +/obj/machinery/status_display/evac/directional/north, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "rWU" = ( /obj/machinery/door/airlock/public/glass{ name = "Prison Wing" @@ -59034,37 +59043,6 @@ }, /turf/open/floor/iron/dark/smooth_large, /area/station/security/processing) -"rYk" = ( -/obj/machinery/button/flasher{ - id = "hopflash"; - pixel_x = 8; - pixel_y = -32 - }, -/obj/machinery/button/door/directional/south{ - id = "hopqueue"; - name = "Queue Shutters Control"; - pixel_x = -8; - req_access = list("hop") - }, -/obj/machinery/button/door/directional/south{ - id = "hop"; - name = "Privacy Shutters Control"; - pixel_x = 8; - req_access = list("hop") - }, -/obj/machinery/button/ticket_machine{ - pixel_x = -8; - pixel_y = -32 - }, -/obj/effect/turf_decal/tile/blue/anticorner/contrasted{ - dir = 8 - }, -/obj/machinery/modular_computer/preset/id{ - dir = 1 - }, -/obj/item/paper/fluff/ids_for_dummies, -/turf/open/floor/iron, -/area/station/command/heads_quarters/hop) "rYq" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -59186,10 +59164,6 @@ dir = 4 }, /area/station/service/chapel) -"sao" = ( -/obj/item/kirbyplants/random, -/turf/open/floor/iron/dark/textured, -/area/station/security/office) "sbc" = ( /obj/structure/table/reinforced, /obj/machinery/door/firedoor, @@ -59598,6 +59572,15 @@ }, /turf/open/floor/iron, /area/mine/production) +"shy" = ( +/obj/machinery/modular_computer/preset/cargochat/medical{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/filled/end{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/medical/medbay/aft) "shB" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -60038,6 +60021,15 @@ /obj/machinery/microwave, /turf/open/floor/plating, /area/station/maintenance/port/aft) +"snG" = ( +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 8 + }, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "snI" = ( /obj/structure/extinguisher_cabinet/directional/west, /obj/machinery/vending/modularpc, @@ -60951,6 +60943,14 @@ }, /turf/open/floor/plating, /area/station/maintenance/department/crew_quarters/bar) +"sAj" = ( +/obj/machinery/photocopier, +/obj/effect/turf_decal/tile/red/half/contrasted{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark/textured, +/area/station/security/office) "sAu" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -61129,7 +61129,7 @@ "sDA" = ( /obj/machinery/igniter/incinerator_ordmix, /turf/open/floor/engine/vacuum, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "sDQ" = ( /obj/item/radio/intercom/prison/directional/north, /obj/effect/turf_decal/tile/red/half/contrasted{ @@ -62224,6 +62224,13 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/wood, /area/station/maintenance/port/aft) +"sUT" = ( +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 4 + }, +/obj/structure/extinguisher_cabinet/directional/east, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "sVf" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -62376,14 +62383,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, /area/station/science/explab) -"sXG" = ( -/obj/structure/cable, -/obj/effect/turf_decal/tile/red/half/contrasted{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron/dark/textured, -/area/station/security/office) "sXK" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -64194,6 +64193,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) +"tDA" = ( +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 5 + }, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/structure/tank_holder/extinguisher, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "tDL" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/red/anticorner/contrasted{ @@ -64926,11 +64935,6 @@ /obj/structure/sign/warning/electric_shock, /turf/open/floor/plating, /area/station/science/xenobiology) -"tOg" = ( -/obj/machinery/power/smes/full, -/obj/structure/cable, -/turf/open/floor/circuit, -/area/station/ai_monitored/turret_protected/ai) "tOi" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -65191,6 +65195,26 @@ /obj/effect/spawner/random/trash/moisture_trap, /turf/open/floor/plating, /area/station/maintenance/department/chapel) +"tUz" = ( +/obj/machinery/button/door/directional/north{ + id = "permainner"; + name = "Inner Bolt Control"; + normaldoorcontrol = 1; + pixel_x = -6; + req_access = list("brig"); + specialfunctions = 4 + }, +/obj/machinery/button/door/directional/north{ + id = "permaouter"; + name = "Outer Bolt Control"; + normaldoorcontrol = 1; + pixel_x = 6; + req_access = list("brig"); + specialfunctions = 4 + }, +/obj/machinery/photobooth/security, +/turf/open/floor/iron/smooth, +/area/station/security/execution/transfer) "tUC" = ( /obj/effect/landmark/event_spawn, /obj/machinery/light/floor, @@ -65401,11 +65425,6 @@ }, /turf/open/floor/iron, /area/station/engineering/main) -"tXL" = ( -/obj/effect/turf_decal/tile/brown/fourcorners, -/obj/machinery/modular_computer/preset/cargochat/engineering, -/turf/open/floor/iron/dark, -/area/station/engineering/lobby) "tXV" = ( /obj/machinery/airalarm/directional/north, /obj/machinery/camera/directional/north{ @@ -66046,6 +66065,18 @@ /obj/effect/turf_decal/siding/thinplating/dark, /turf/open/floor/plating, /area/station/service/hydroponics) +"uiF" = ( +/obj/structure/cable, +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 1 + }, +/obj/machinery/power/apc/auto_name/directional/north, +/obj/item/kirbyplants/random, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "uiI" = ( /obj/structure/rack, /obj/effect/spawner/random/maintenance/three, @@ -66238,6 +66269,19 @@ /obj/structure/sign/warning/docking/directional/south, /turf/open/misc/asteroid/snow/icemoon, /area/icemoon/surface/outdoors/nospawn) +"uml" = ( +/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/warning{ + dir = 8 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable, +/obj/structure/disposalpipe/segment, +/turf/open/floor/iron/white, +/area/station/medical/medbay/aft) "umv" = ( /obj/effect/turf_decal/siding/white{ dir = 9 @@ -68603,6 +68647,20 @@ }, /turf/open/floor/engine, /area/station/engineering/atmos/hfr_room) +"vbg" = ( +/obj/structure/cable, +/obj/machinery/power/smes/full, +/obj/machinery/camera/directional/south{ + c_tag = "Labor Camp Utilities"; + network = list("labor") + }, +/turf/open/floor/iron/smooth, +/area/mine/laborcamp/security) +"vbn" = ( +/obj/machinery/power/smes/full, +/obj/structure/cable, +/turf/open/floor/circuit/telecomms/mainframe, +/area/station/tcommsat/server) "vbz" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -69527,21 +69585,6 @@ /obj/item/radio/intercom/directional/south, /turf/open/floor/iron/dark, /area/station/medical/virology) -"vqJ" = ( -/obj/machinery/requests_console/directional/north{ - department = "Security"; - name = "Security Requests Console" - }, -/obj/effect/mapping_helpers/requests_console/information, -/obj/effect/mapping_helpers/requests_console/assistance, -/obj/effect/turf_decal/tile/red/anticorner, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/turf/open/floor/iron/dark/textured_corner{ - dir = 1 - }, -/area/station/security/office) "vqN" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -69577,12 +69620,6 @@ /obj/item/kirbyplants/random, /turf/open/floor/iron, /area/station/security/courtroom) -"vry" = ( -/obj/machinery/button/photobooth{ - pixel_y = -26 - }, -/turf/open/floor/iron, -/area/station/command/heads_quarters/hop) "vrC" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -70382,13 +70419,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/security/brig/entrance) -"vDg" = ( -/obj/machinery/newscaster/directional/south, -/obj/item/kirbyplants/random, -/turf/open/floor/iron/white/side{ - dir = 5 - }, -/area/station/science/lab) "vDh" = ( /obj/structure/table/glass, /obj/item/storage/box/beakers{ @@ -70880,10 +70910,6 @@ /obj/machinery/holopad, /turf/open/floor/iron/kitchen/diagonal, /area/station/service/kitchen) -"vMz" = ( -/obj/machinery/photobooth, -/turf/open/floor/iron, -/area/station/hallway/primary/central) "vMA" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -71588,17 +71614,6 @@ /obj/structure/barricade/wooden/snowed, /turf/open/misc/asteroid/snow/icemoon, /area/icemoon/surface/outdoors/nospawn) -"vYr" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/structure/table, -/obj/item/pen{ - pixel_x = -5 - }, -/obj/item/paper_bin, -/turf/open/floor/plating, -/area/station/hallway/secondary/service) "vYs" = ( /obj/machinery/light/directional/east, /obj/structure/cable, @@ -72857,14 +72872,6 @@ }, /turf/open/floor/iron/dark, /area/station/maintenance/disposal) -"wry" = ( -/obj/machinery/photocopier, -/obj/effect/turf_decal/tile/red/half/contrasted{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/dark/textured, -/area/station/security/office) "wrA" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/public/glass{ @@ -73787,18 +73794,10 @@ /obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance/departmental, /turf/open/floor/plating, /area/station/maintenance/port/aft) -"wFo" = ( -/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/warning{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/turf/open/floor/iron/white, -/area/station/medical/medbay/aft) +"wFN" = ( +/mob/living/basic/slime, +/turf/open/floor/engine, +/area/station/science/xenobiology) "wFO" = ( /obj/effect/landmark/start/hangover, /obj/effect/turf_decal/siding/wood{ @@ -73908,7 +73907,7 @@ "wHd" = ( /obj/machinery/atmospherics/pipe/smart/simple/dark/visible, /turf/closed/wall/r_wall, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "wHe" = ( /obj/structure/cable, /turf/open/floor/iron/dark/textured, @@ -74385,7 +74384,7 @@ }, /obj/effect/mapping_helpers/airlock/access/all/science/ordnance, /turf/open/floor/engine, -/area/station/science/ordnance/burnchamber) +/area/station/science/ordnance) "wPD" = ( /obj/machinery/door/airlock/security/glass{ name = "Evidence Storage" @@ -74945,6 +74944,12 @@ /obj/effect/turf_decal/tile/brown/half/contrasted, /turf/open/floor/iron, /area/station/cargo/office) +"wXW" = ( +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/hallway/primary/central) "wXX" = ( /obj/machinery/door/window/right/directional/west{ name = "Containment Pen 10"; @@ -75197,6 +75202,10 @@ "xaI" = ( /turf/open/floor/iron/dark/telecomms, /area/station/tcommsat/server) +"xaJ" = ( +/obj/item/kirbyplants/random, +/turf/open/floor/iron/dark/textured, +/area/station/security/office) "xaO" = ( /obj/effect/spawner/random/trash/moisture_trap, /obj/machinery/light/small/directional/west, @@ -75540,26 +75549,6 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/glass/reinforced, /area/station/ai_monitored/security/armory/upper) -"xge" = ( -/obj/machinery/button/door/directional/north{ - id = "permainner"; - name = "Inner Bolt Control"; - normaldoorcontrol = 1; - pixel_x = -6; - req_access = list("brig"); - specialfunctions = 4 - }, -/obj/machinery/button/door/directional/north{ - id = "permaouter"; - name = "Outer Bolt Control"; - normaldoorcontrol = 1; - pixel_x = 6; - req_access = list("brig"); - specialfunctions = 4 - }, -/obj/machinery/photobooth/security, -/turf/open/floor/iron/smooth, -/area/station/security/execution/transfer) "xgg" = ( /obj/structure/rack, /obj/item/clothing/suit/hooded/wintercoat/eva{ @@ -76847,6 +76836,9 @@ /obj/structure/extinguisher_cabinet/directional/east, /turf/open/floor/iron/dark, /area/station/maintenance/disposal/incinerator) +"xAn" = ( +/turf/open/floor/iron/dark, +/area/station/engineering/lobby) "xAs" = ( /turf/closed/wall/r_wall, /area/icemoon/surface/outdoors/nospawn) @@ -77635,6 +77627,15 @@ /obj/effect/mapping_helpers/ianbirthday, /turf/open/floor/carpet, /area/station/command/heads_quarters/hop) +"xMR" = ( +/obj/effect/turf_decal/tile/blue/half/contrasted{ + dir = 8 + }, +/obj/structure/chair/office{ + dir = 8 + }, +/turf/open/floor/iron, +/area/station/command/heads_quarters/hop) "xMT" = ( /turf/closed/wall, /area/station/science/research) @@ -114615,7 +114616,7 @@ iDt nTO ody hMJ -hfw +vbg nTO iDt xMq @@ -116640,7 +116641,7 @@ dhq dhq iDt iDt -iDt +grY iDt dLN rbT @@ -116904,7 +116905,7 @@ rbT lLN vRO ggV -eYz +cSm tGP tGP iRp @@ -172462,7 +172463,7 @@ uME doq trA uME -xge +tUz hBg dzt kvu @@ -187447,10 +187448,10 @@ tsa wHb qLY abe -hIK +wFN abe cKA -hIK +wFN abe cKA abe @@ -189503,7 +189504,7 @@ abe abe gLj abe -hIK +wFN gLj abe abe @@ -193601,10 +193602,10 @@ thA thA rcY iDt -egf -egf -egf -egf +uIf +uIf +uIf +uIf fSG fSG bId @@ -235229,7 +235230,7 @@ xzh dnq qcu bDR -hYW +wXW mpy bep ylU @@ -235255,7 +235256,7 @@ vjx mDf nLb kNp -gYP +vbn vFs mMk qAV @@ -235743,7 +235744,7 @@ iIA fSC iIA cvg -vMz +qQb jII okb ylU @@ -236252,12 +236253,12 @@ dkb kmi iYb xaA -gnA +crH wjv pec fJl -iaS -rYk +xMR +bJy cpm dnq ylU @@ -236514,7 +236515,7 @@ ool jRC cgC jaq -vry +cua cpm dnq ylU @@ -236955,10 +236956,10 @@ aBR aBR lbc nbp -dNv -sXG +lIt +hdn ijj -hpc +nbw lRF feJ mgZ @@ -237212,7 +237213,7 @@ aBR aBR nbp nbp -vqJ +hjX omk omk jeF @@ -237731,7 +237732,7 @@ sMY wMV qqM wMi -sao +xaJ arA jwx kfy @@ -238240,12 +238241,12 @@ bln lBD nbp nbp -hGj +ezs jeF omk jeF nQf -mMf +pCE arA rYB rgC @@ -238497,8 +238498,8 @@ tGr bln lbc nbp -kbz -wry +jOS +sAj dlK pbI jIm @@ -240136,7 +240137,7 @@ elj iRr omi tKi -tXL +czl ydg dAm szR @@ -240393,7 +240394,7 @@ jkx fLq hro tKi -gTf +kCG dxA oht rSC @@ -240650,7 +240651,7 @@ gwK jyR bID bID -hio +fvA vCK rSC rSC @@ -241163,7 +241164,7 @@ gMN xnE tvd egV -nYm +xAn syU vYJ fGn @@ -246251,7 +246252,7 @@ gzw kiB kQX kyZ -vYr +bFw mdZ rth hid @@ -248685,7 +248686,7 @@ mlp lEg cvh uBi -tOg +eYH jIZ oFx iHp @@ -248885,7 +248886,7 @@ oqc oAD xKX vep -clr +pBI sCm gGo bTQ @@ -249117,7 +249118,7 @@ tAx wbN grT lEo -fEY +shy qQp bVp jnS @@ -249374,7 +249375,7 @@ xyc dVw bkV ree -gkf +mpR qQp tQc jbx @@ -249629,12 +249630,12 @@ kNa ica lDM klc -qHa -iuK -bmZ +rWR +rqd +snG mJj laD -lWS +uml laD laD laD @@ -249886,16 +249887,16 @@ vzN oXq xWT klc -oTE +uiF pJX -ijf +qxu lPr vcY mmR -bsR +mOM dMp dMp -khv +kVS lqG grD xZW @@ -250143,16 +250144,16 @@ bNH rIc tVB klc -akG +tDA gsT -eUH +eDH iYs xFo rvA -wFo -qCH -qKN -nqt +dVc +nfD +sUT +bIQ fFJ hRA npo @@ -257589,7 +257590,7 @@ ljF ljF sDg gXJ -vDg +hhP oHK iZl iZl diff --git a/_maps/map_files/Mining/Lavaland.dmm b/_maps/map_files/Mining/Lavaland.dmm index 712e555b878..6a1d703aea4 100644 --- a/_maps/map_files/Mining/Lavaland.dmm +++ b/_maps/map_files/Mining/Lavaland.dmm @@ -166,14 +166,6 @@ /obj/effect/turf_decal/siding/yellow, /turf/open/floor/carpet/royalblue, /area/mine/living_quarters) -"bq" = ( -/obj/structure/railing{ - dir = 1 - }, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/white/line, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors) "bt" = ( /obj/structure/disposalpipe/segment{ dir = 5 @@ -191,14 +183,6 @@ }, /turf/open/floor/iron/edge, /area/mine/lounge) -"bx" = ( -/obj/machinery/airalarm/directional/north, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 9 - }, -/obj/structure/ore_box, -/turf/open/floor/iron/dark, -/area/mine/production) "by" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/siding/wideplating_new{ @@ -295,12 +279,6 @@ /obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance/departmental, /turf/open/floor/plating, /area/mine/maintenance/living/north) -"cg" = ( -/obj/structure/cable, -/obj/machinery/power/smes/full, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, -/area/mine/maintenance/service) "ch" = ( /obj/machinery/power/apc/auto_name/directional/west, /obj/structure/cable, @@ -535,12 +513,6 @@ /obj/structure/lattice/catwalk/mining, /turf/open/lava/smooth/lava_land_surface, /area/lavaland/surface/outdoors) -"dp" = ( -/obj/structure/ore_vent/starter_resources{ - icon_state = "ore_vent_active" - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors) "dq" = ( /obj/structure/stone_tile{ dir = 4 @@ -630,13 +602,18 @@ }, /turf/open/floor/iron/dark/smooth_edge, /area/mine/production) -"dW" = ( -/obj/structure/lattice/catwalk/mining, -/obj/structure/railing, -/obj/structure/railing{ - dir = 1 +"dV" = ( +/obj/structure/railing/corner{ + dir = 4 }, -/turf/open/lava/smooth/lava_land_surface, +/obj/structure/railing/corner, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/white/line{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "ee" = ( /obj/machinery/shower/directional/south, @@ -824,6 +801,16 @@ }, /turf/open/floor/iron/checker, /area/mine/cafeteria) +"fx" = ( +/obj/structure/railing, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/white/line{ + dir = 1 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "fA" = ( /obj/machinery/computer/shuttle/mining{ dir = 1 @@ -883,6 +870,10 @@ }, /turf/open/floor/plating/lavaland_atmos, /area/lavaland/surface/outdoors) +"fP" = ( +/obj/structure/gulag_vent, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "fQ" = ( /turf/open/genturf, /area/lavaland/surface/outdoors/unexplored/danger) @@ -894,14 +885,6 @@ dir = 1 }, /area/mine/laborcamp/security) -"fT" = ( -/obj/effect/turf_decal/loading_area, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 5 - }, -/obj/structure/closet/crate/bin, -/turf/open/floor/iron/dark, -/area/mine/production) "fU" = ( /obj/machinery/portable_atmospherics/canister/oxygen, /turf/open/floor/plating, @@ -1041,6 +1024,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/carpet, /area/mine/living_quarters) +"gA" = ( +/obj/structure/lattice/catwalk/mining, +/obj/structure/railing, +/obj/structure/railing{ + dir = 1 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors) "gB" = ( /obj/structure/lattice/catwalk, /obj/structure/disposalpipe/segment{ @@ -1135,6 +1126,14 @@ /obj/effect/turf_decal/sand/plating/volcanic, /turf/open/floor/plating/lavaland_atmos, /area/mine/maintenance/service/disposals) +"gW" = ( +/obj/machinery/airalarm/directional/north, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 9 + }, +/obj/structure/ore_box, +/turf/open/floor/iron/dark, +/area/mine/production) "gZ" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 @@ -1538,13 +1537,6 @@ /obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance, /turf/open/floor/plating, /area/mine/maintenance/public/north) -"jk" = ( -/obj/structure/table, -/obj/item/storage/box/bandages{ - pixel_y = 6 - }, -/turf/open/floor/iron/white, -/area/mine/laborcamp/production) "jm" = ( /obj/machinery/door/airlock/public/glass{ name = "Showers" @@ -1578,6 +1570,16 @@ /obj/structure/extinguisher_cabinet/directional/north, /turf/open/floor/iron/edge, /area/mine/living_quarters) +"js" = ( +/obj/structure/lattice/catwalk/mining, +/obj/structure/railing/corner{ + dir = 8 + }, +/obj/structure/railing/corner{ + dir = 1 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors) "jw" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -1722,24 +1724,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/mine/maintenance/living/north) -"kx" = ( -/obj/effect/turf_decal/trimline/brown/filled/line, -/obj/structure/table, -/obj/item/paper/fluff/stations/lavaland/orm_notice, -/turf/open/floor/iron/dark/smooth_edge{ - dir = 1 - }, -/area/mine/production) -"ky" = ( -/obj/structure/railing{ - dir = 6 - }, -/obj/effect/turf_decal/stripes/corner{ - dir = 1 - }, -/obj/machinery/light/directional/south, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors) "kB" = ( /obj/structure/stone_tile/surrounding_tile, /obj/structure/stone_tile/surrounding_tile{ @@ -1783,6 +1767,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply, /turf/open/floor/plating, /area/mine/maintenance/service) +"kG" = ( +/obj/structure/railing{ + dir = 5 + }, +/obj/effect/turf_decal/stripes/corner{ + dir = 8 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "kH" = ( /obj/structure/stone_tile/surrounding_tile{ dir = 1 @@ -1980,17 +1973,6 @@ }, /turf/open/lava/smooth/lava_land_surface, /area/lavaland/surface/outdoors) -"lA" = ( -/obj/machinery/recycler{ - dir = 8 - }, -/obj/machinery/conveyor{ - dir = 4; - id = "mining_disposals" - }, -/obj/effect/turf_decal/sand/plating/volcanic, -/turf/open/floor/plating/lavaland_atmos, -/area/mine/maintenance/service/disposals) "lC" = ( /obj/structure/stone_tile/block/cracked{ dir = 1 @@ -2105,18 +2087,6 @@ }, /turf/open/lava/smooth/lava_land_surface, /area/lavaland/surface/outdoors) -"lT" = ( -/obj/structure/railing{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/white/line{ - dir = 4 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors) "lV" = ( /obj/structure/cable, /obj/effect/turf_decal/trimline/red/filled/line{ @@ -2182,19 +2152,6 @@ /obj/structure/cable, /turf/open/floor/iron/dark/textured_large, /area/mine/hydroponics) -"mh" = ( -/obj/structure/railing/corner{ - dir = 4 - }, -/obj/structure/railing/corner, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/white/line{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors) "mj" = ( /obj/structure/stone_tile/block, /obj/structure/stone_tile/block{ @@ -2745,6 +2702,13 @@ /obj/effect/turf_decal/trimline/brown/filled/line, /turf/open/floor/iron/dark/textured_large, /area/mine/production) +"oy" = ( +/obj/structure/lattice/catwalk/mining, +/obj/structure/railing{ + dir = 8 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors) "oA" = ( /turf/closed/wall, /area/mine/storage) @@ -2870,6 +2834,12 @@ /obj/effect/spawner/random/trash/mess, /turf/open/floor/iron/white, /area/mine/laborcamp/production) +"ps" = ( +/obj/structure/cable, +/obj/machinery/power/smes/full, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/mine/maintenance/service) "pu" = ( /obj/item/chair/stool{ pixel_x = -2; @@ -3310,6 +3280,23 @@ }, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"so" = ( +/obj/structure/table, +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 10 + }, +/obj/item/storage/box/bandages{ + pixel_y = 6; + pixel_x = 4 + }, +/obj/item/storage/pill_bottle/epinephrine{ + pixel_x = -6; + pixel_y = 4 + }, +/turf/open/floor/iron/white/smooth_corner{ + dir = 8 + }, +/area/mine/medical) "st" = ( /obj/structure/chair/stool/directional/north, /obj/effect/decal/cleanable/dirt, @@ -3531,15 +3518,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/mine/storage) -"tO" = ( -/obj/machinery/power/apc/auto_name/directional/south, -/obj/structure/cable, -/obj/effect/turf_decal/trimline/brown/filled/line, -/obj/structure/table, -/turf/open/floor/iron/dark/smooth_edge{ - dir = 1 - }, -/area/mine/production) "tV" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, @@ -4308,15 +4286,6 @@ }, /turf/open/floor/iron/checker, /area/mine/cafeteria) -"yQ" = ( -/obj/structure/railing{ - dir = 5 - }, -/obj/effect/turf_decal/stripes/corner{ - dir = 8 - }, -/turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors) "yR" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -4442,6 +4411,14 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/mine/maintenance/living/north) +"zD" = ( +/obj/effect/turf_decal/loading_area{ + dir = 1 + }, +/obj/structure/barricade/wooden/crude, +/obj/structure/barricade/wooden, +/turf/open/floor/iron/dark, +/area/mine/production) "zF" = ( /obj/item/kirbyplants/random, /obj/effect/turf_decal/trimline/blue/filled/line{ @@ -4474,6 +4451,18 @@ /obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance/departmental, /turf/open/floor/plating, /area/mine/maintenance/service) +"zO" = ( +/obj/structure/railing{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/white/line{ + dir = 4 + }, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "zQ" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/smooth_edge, @@ -4494,14 +4483,6 @@ /obj/structure/cable, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) -"Ac" = ( -/obj/effect/turf_decal/bot, -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 10 - }, -/obj/machinery/computer/order_console/mining, -/turf/open/floor/iron/dark, -/area/mine/production) "Ae" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -4509,14 +4490,6 @@ /obj/structure/lattice/catwalk, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) -"Af" = ( -/obj/machinery/mineral/processing_unit{ - dir = 1; - input_dir = 8; - output_dir = 4 - }, -/turf/open/floor/plating, -/area/mine/laborcamp/production) "Ai" = ( /obj/structure/stone_tile/cracked{ dir = 1 @@ -4616,13 +4589,6 @@ "AX" = ( /turf/open/floor/plating, /area/mine/laborcamp/security/maintenance) -"AY" = ( -/obj/structure/lattice/catwalk/mining, -/obj/structure/railing{ - dir = 9 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors) "Bb" = ( /obj/machinery/camera/autoname/directional/east{ network = list("mine") @@ -4991,6 +4957,11 @@ /obj/effect/turf_decal/sand/plating/volcanic, /turf/open/floor/plating/lavaland_atmos, /area/lavaland/surface/outdoors) +"Ee" = ( +/obj/machinery/power/smes/full, +/obj/structure/cable, +/turf/open/floor/plating, +/area/mine/maintenance/labor) "Eg" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/disposalpipe/segment, @@ -5004,14 +4975,12 @@ /turf/open/floor/plating/lavaland_atmos, /area/mine/maintenance/service/disposals) "Ep" = ( -/obj/structure/lattice/catwalk/mining, -/obj/structure/railing/corner{ - dir = 8 - }, -/obj/structure/railing/corner{ +/obj/structure/railing{ dir = 1 }, -/turf/open/lava/smooth/lava_land_surface, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/white/line, +/turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "Eq" = ( /obj/machinery/door/airlock/security/glass{ @@ -5357,13 +5326,6 @@ }, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) -"GV" = ( -/obj/structure/lattice/catwalk/mining, -/obj/structure/railing{ - dir = 8 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors) "GW" = ( /obj/structure/chair/office{ dir = 1 @@ -5407,11 +5369,6 @@ /obj/machinery/power/apc/auto_name/directional/north, /turf/open/floor/plating, /area/mine/maintenance/public/north) -"Hi" = ( -/obj/machinery/power/smes/full, -/obj/structure/cable, -/turf/open/floor/plating, -/area/mine/maintenance/labor) "Hp" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /obj/effect/turf_decal/trimline/brown/filled/line{ @@ -5793,6 +5750,13 @@ /obj/machinery/light/small/directional/south, /turf/open/floor/plating, /area/mine/laborcamp/production) +"Jz" = ( +/obj/structure/lattice/catwalk/mining, +/obj/structure/railing{ + dir = 10 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors) "JA" = ( /obj/machinery/computer/shuttle/mining/common, /obj/structure/sign/directions/evac/directional/east{ @@ -5879,13 +5843,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating, /area/mine/laborcamp/security/maintenance) -"JO" = ( -/obj/structure/lattice/catwalk/mining, -/obj/structure/railing{ - dir = 10 - }, -/turf/open/lava/smooth/lava_land_surface, -/area/lavaland/surface/outdoors) "JP" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -5898,23 +5855,6 @@ dir = 1 }, /area/mine/living_quarters) -"JQ" = ( -/obj/structure/table, -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 10 - }, -/obj/item/storage/box/bandages{ - pixel_y = 6; - pixel_x = 4 - }, -/obj/item/storage/pill_bottle/epinephrine{ - pixel_x = -6; - pixel_y = 4 - }, -/turf/open/floor/iron/white/smooth_corner{ - dir = 8 - }, -/area/mine/medical) "JR" = ( /obj/structure/stone_tile, /obj/structure/stone_tile{ @@ -6290,6 +6230,13 @@ dir = 4 }, /area/mine/lounge) +"LO" = ( +/obj/structure/table, +/obj/item/storage/box/bandages{ + pixel_y = 6 + }, +/turf/open/floor/iron/white, +/area/mine/laborcamp/production) "LR" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -6306,6 +6253,14 @@ }, /turf/open/floor/plating/lavaland_atmos, /area/lavaland/surface/outdoors) +"LT" = ( +/obj/machinery/mineral/processing_unit/gulag{ + dir = 1; + input_dir = 8; + output_dir = 4 + }, +/turf/open/floor/plating, +/area/mine/laborcamp/production) "LY" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 @@ -6576,6 +6531,14 @@ /obj/effect/turf_decal/tile/blue/fourcorners, /turf/open/floor/iron, /area/mine/living_quarters) +"NG" = ( +/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 10 + }, +/obj/machinery/computer/order_console/mining, +/turf/open/floor/iron/dark, +/area/mine/production) "NL" = ( /obj/structure/railing, /obj/structure/lattice/catwalk/mining, @@ -6878,6 +6841,17 @@ }, /turf/open/floor/plating, /area/mine/production) +"PL" = ( +/obj/machinery/recycler{ + dir = 8 + }, +/obj/machinery/conveyor{ + dir = 4; + id = "mining_disposals" + }, +/obj/effect/turf_decal/sand/plating/volcanic, +/turf/open/floor/plating/lavaland_atmos, +/area/mine/maintenance/service/disposals) "PR" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/carpet/executive, @@ -6959,13 +6933,9 @@ }, /turf/open/floor/iron/dark, /area/mine/mechbay) -"Qm" = ( -/obj/structure/railing, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/effect/turf_decal/stripes/white/line{ - dir = 1 +"Qq" = ( +/obj/structure/ore_vent/starter_resources{ + icon_state = "ore_vent_active" }, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) @@ -7056,6 +7026,16 @@ dir = 4 }, /area/mine/production) +"QV" = ( +/obj/structure/railing{ + dir = 6 + }, +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/obj/machinery/light/directional/south, +/turf/open/misc/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) "QX" = ( /turf/closed/wall, /area/mine/mechbay) @@ -7100,6 +7080,14 @@ }, /turf/open/floor/iron/dark, /area/mine/production) +"Ro" = ( +/obj/effect/turf_decal/loading_area, +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 5 + }, +/obj/structure/closet/crate/bin, +/turf/open/floor/iron/dark, +/area/mine/production) "Rs" = ( /obj/machinery/conveyor{ dir = 6; @@ -7176,14 +7164,6 @@ /obj/structure/lattice/catwalk, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) -"RS" = ( -/obj/effect/turf_decal/loading_area{ - dir = 1 - }, -/obj/structure/barricade/wooden/crude, -/obj/structure/barricade/wooden, -/turf/open/floor/iron/dark, -/area/mine/production) "RV" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 4 @@ -7385,6 +7365,14 @@ }, /turf/open/floor/iron/dark/smooth_edge, /area/mine/eva) +"Ti" = ( +/obj/effect/turf_decal/trimline/brown/filled/line, +/obj/structure/table, +/obj/item/paper/fluff/stations/lavaland/orm_notice, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 1 + }, +/area/mine/production) "To" = ( /obj/structure/table, /obj/machinery/reagentgrinder, @@ -7432,6 +7420,13 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/mine/maintenance/living/north) +"TD" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 1 + }, +/obj/structure/ore_box, +/turf/open/floor/iron/dark/smooth_edge, +/area/mine/production) "TF" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -7660,13 +7655,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating, /area/mine/laborcamp/security/maintenance) -"UW" = ( -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 1 - }, -/obj/structure/ore_box, -/turf/open/floor/iron/dark/smooth_edge, -/area/mine/production) "UZ" = ( /obj/structure/chair/stool/directional/west, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -7847,6 +7835,15 @@ }, /turf/open/floor/iron/dark/textured_large, /area/mine/laborcamp) +"VZ" = ( +/obj/machinery/power/apc/auto_name/directional/south, +/obj/structure/cable, +/obj/effect/turf_decal/trimline/brown/filled/line, +/obj/structure/table, +/turf/open/floor/iron/dark/smooth_edge{ + dir = 1 + }, +/area/mine/production) "Wb" = ( /obj/structure/cable, /turf/open/floor/iron/dark/textured_large, @@ -7894,6 +7891,13 @@ }, /turf/open/floor/carpet/neon/simple/red/nodots, /area/mine/cafeteria) +"Wy" = ( +/obj/structure/lattice/catwalk/mining, +/obj/structure/railing{ + dir = 9 + }, +/turf/open/lava/smooth/lava_land_surface, +/area/lavaland/surface/outdoors) "WB" = ( /obj/machinery/disposal/bin, /obj/structure/disposalpipe/trunk, @@ -22569,7 +22573,7 @@ uU uU uU pU -pU +fP pU ff Gf @@ -23851,7 +23855,7 @@ aj aj eR Kw -jk +LO ff mU Fv @@ -24373,7 +24377,7 @@ Hd Nb NR Kv -Af +LT ff gm mN @@ -28234,7 +28238,7 @@ Zt Zt Zt Zt -Hi +Ee ve RD RD @@ -36428,7 +36432,7 @@ pU mA su xG -lA +PL Sd pU aj @@ -38481,7 +38485,7 @@ Ue AA gB ON -cg +ps gq ER vc @@ -39546,7 +39550,7 @@ yp yp Dz LG -JQ +so It Xp Ss @@ -45941,9 +45945,9 @@ pU aj aj aj -AY -lT -JO +Wy +zO +Jz aj oA Lu @@ -46198,9 +46202,9 @@ aj aj aj aj -bq -dp -Qm +Ep +Qq +fx aj oA Lz @@ -46455,9 +46459,9 @@ pU pU aj aj -yQ -mh -ky +kG +dV +QV NU NU NU @@ -46713,7 +46717,7 @@ pU pU aj aj -dW +gA aj Le Lh @@ -46969,8 +46973,8 @@ pU pU AQ ZM -GV -Ep +oy +js ZM Ki Uq @@ -47748,10 +47752,10 @@ NU NU NU NU -bx +gW Xj QT -Ac +NG pK No Hp @@ -48004,11 +48008,11 @@ pU pU NU PI -RS -UW +zD +TD Vw wl -kx +Ti pK lg se @@ -48265,7 +48269,7 @@ zJ oi Ts Wb -tO +VZ pK Tf Jp @@ -48777,7 +48781,7 @@ NU Rs rP JG -fT +Ro op NU pK diff --git a/_maps/map_files/moonstation/moonstation.dmm b/_maps/map_files/moonstation/moonstation.dmm index 113286d3f2e..e88f96a3a4b 100644 --- a/_maps/map_files/moonstation/moonstation.dmm +++ b/_maps/map_files/moonstation/moonstation.dmm @@ -2203,7 +2203,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "aGg" = ( /obj/effect/turf_decal/siding/wood, /obj/structure/table/wood/fancy/black, @@ -3238,7 +3238,7 @@ "aTX" = ( /obj/effect/landmark/start/barber, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "aUc" = ( /obj/effect/turf_decal/siding/dark{ dir = 1 @@ -6701,7 +6701,7 @@ /obj/effect/spawner/structure/window, /obj/structure/curtain/cloth/fancy, /turf/open/floor/plating, -/area/station/service/salon) +/area/station/service/barber) "caA" = ( /obj/machinery/duct, /obj/structure/railing, @@ -9425,7 +9425,7 @@ dir = 1 }, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "cTi" = ( /obj/effect/turf_decal/stripes/asteroid/line{ dir = 4 @@ -13499,7 +13499,7 @@ }, /obj/structure/mirror/directional/north, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "eeh" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/smart/simple/dark/visible, @@ -14906,7 +14906,7 @@ /obj/item/scissors, /obj/machinery/airalarm/directional/west, /turf/open/floor/wood, -/area/station/service/salon) +/area/station/service/barber) "ewW" = ( /obj/structure/bed{ dir = 4 @@ -23648,7 +23648,7 @@ dir = 4 }, /turf/open/floor/iron/dark, -/area/station/service/salon) +/area/station/service/barber) "hbo" = ( /obj/machinery/firealarm/directional/east, /obj/effect/turf_decal/tile/blue/half/contrasted{ @@ -27741,7 +27741,7 @@ /obj/structure/mirror/directional/west, /obj/item/radio/intercom/directional/south, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "ioY" = ( /obj/machinery/door/airlock/research{ glass = 1; @@ -29910,7 +29910,7 @@ }, /obj/machinery/light/small/directional/south, /turf/open/floor/wood, -/area/station/service/salon) +/area/station/service/barber) "iWP" = ( /obj/effect/turf_decal/tile/red{ dir = 8 @@ -29928,7 +29928,7 @@ /obj/effect/mapping_helpers/airlock/access/any/service/general, /obj/machinery/door/firedoor, /turf/open/floor/wood, -/area/station/service/salon) +/area/station/service/barber) "iXp" = ( /obj/structure/sign/poster/random/directional/east, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -30286,7 +30286,7 @@ /obj/structure/cable, /obj/machinery/camera/autoname/directional/west, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "jbG" = ( /obj/effect/turf_decal/weather/snow, /obj/machinery/light/small/directional/south, @@ -36523,7 +36523,7 @@ /obj/structure/cable, /obj/machinery/holopad, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "kVm" = ( /obj/effect/turf_decal/tile/neutral/half/contrasted, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -38287,7 +38287,7 @@ /obj/item/hairbrush, /obj/item/hhmirror, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "luN" = ( /obj/machinery/door/airlock/research{ autoclose = 0; @@ -38659,7 +38659,7 @@ "lAp" = ( /obj/machinery/airalarm/directional/west, /turf/open/floor/wood, -/area/station/service/salon) +/area/station/service/barber) "lAr" = ( /obj/effect/turf_decal/tile/dark_green/half/contrasted{ dir = 1 @@ -39993,7 +39993,7 @@ "lUc" = ( /obj/machinery/camera/autoname/directional/south, /turf/open/floor/wood, -/area/station/service/salon) +/area/station/service/barber) "lUn" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/item/radio/intercom/directional/south, @@ -40579,7 +40579,7 @@ dir = 6 }, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "mcV" = ( /obj/structure/reagent_dispensers/beerkeg, /turf/open/floor/wood, @@ -41133,7 +41133,7 @@ }, /obj/structure/mirror/directional/west, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "mmf" = ( /obj/structure/closet/emcloset/anchored, /obj/machinery/light/small/directional/west, @@ -44250,7 +44250,7 @@ /obj/effect/turf_decal/siding/dark, /obj/item/radio/intercom/directional/west, /turf/open/floor/iron/dark, -/area/station/service/salon) +/area/station/service/barber) "nii" = ( /obj/machinery/portable_atmospherics/canister/nitrous_oxide, /obj/effect/turf_decal/bot, @@ -46364,7 +46364,7 @@ /obj/machinery/light/warm/directional/west, /obj/machinery/light_switch/directional/west, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "nPC" = ( /obj/machinery/shieldgen, /obj/machinery/light/warm/directional/north, @@ -53696,7 +53696,7 @@ /area/station/medical/treatment_center) "pXY" = ( /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "pYi" = ( /obj/effect/turf_decal/weather/snow, /obj/effect/turf_decal/weather/snow/corner{ @@ -57591,7 +57591,7 @@ "rej" = ( /obj/item/kirbyplants/random, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "rek" = ( /obj/machinery/vending/cart, /obj/structure/cable, @@ -60743,7 +60743,7 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/effect/landmark/start/barber, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "sbW" = ( /obj/machinery/holopad, /obj/structure/cable, @@ -62180,7 +62180,7 @@ "swQ" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "swX" = ( /obj/effect/spawner/structure/window, /turf/open/floor/plating, @@ -64888,7 +64888,7 @@ /obj/effect/turf_decal/siding/dark, /obj/machinery/vending/barbervend, /turf/open/floor/iron/dark, -/area/station/service/salon) +/area/station/service/barber) "tnQ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -65875,7 +65875,7 @@ "tDY" = ( /obj/machinery/light/small/directional/south, /turf/open/floor/wood, -/area/station/service/salon) +/area/station/service/barber) "tDZ" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -65909,7 +65909,7 @@ /area/station/science/explab) "tEm" = ( /turf/closed/wall/mineral/wood, -/area/station/service/salon) +/area/station/service/barber) "tEn" = ( /obj/structure/window/reinforced/spawner/directional/south, /obj/structure/flora/bush/flowers_br/style_random, @@ -68669,7 +68669,7 @@ /obj/structure/closet/secure_closet/barber, /obj/effect/turf_decal/siding/dark, /turf/open/floor/iron/dark, -/area/station/service/salon) +/area/station/service/barber) "uum" = ( /obj/effect/turf_decal/tile/red/half/contrasted{ dir = 4 @@ -72741,7 +72741,7 @@ "vGA" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "vGH" = ( /turf/closed/wall/rust, /area/station/maintenance/abandon_cafeteria/hydro) @@ -77585,7 +77585,7 @@ dir = 1 }, /turf/open/floor/iron/vaporwave, -/area/station/service/salon) +/area/station/service/barber) "xfZ" = ( /obj/machinery/atmospherics/pipe/layer_manifold/scrubbers/hidden, /turf/open/floor/catwalk_floor, diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index e0de5bebc26..456cf46196e 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -597,16 +597,6 @@ dir = 1 }, /area/station/escapepodbay) -"aci" = ( -/obj/structure/railing{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 4 - }, -/obj/machinery/photobooth/security, -/turf/open/floor/iron, -/area/station/security/execution/transfer) "acj" = ( /turf/open/floor/iron/stairs/medium{ dir = 1 @@ -6018,6 +6008,11 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/science/robotics/lab) +"aUc" = ( +/obj/item/radio/intercom/directional/east, +/obj/machinery/photobooth, +/turf/open/floor/iron/grimy, +/area/station/service/library/lounge) "aUh" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -7521,6 +7516,15 @@ }, /turf/open/floor/iron/white, /area/station/command/heads_quarters/captain/private) +"bCx" = ( +/obj/structure/railing{ + dir = 8 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 8 + }, +/turf/open/floor/glass/reinforced, +/area/station/science/research) "bDf" = ( /obj/structure/table/reinforced, /obj/item/folder/yellow, @@ -8262,6 +8266,12 @@ }, /turf/open/floor/iron, /area/station/commons/storage/primary) +"bNI" = ( +/obj/machinery/airalarm/directional/north, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/modular_computer/preset/cargochat/service, +/turf/open/floor/iron, +/area/station/hallway/secondary/service) "bNJ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -12269,10 +12279,6 @@ "dfz" = ( /turf/closed/wall/r_wall, /area/station/science/ordnance/storage) -"dfC" = ( -/mob/living/basic/slime, -/turf/open/floor/engine, -/area/station/science/xenobiology) "dfE" = ( /obj/effect/turf_decal/trimline/purple/filled/line{ dir = 5 @@ -19485,13 +19491,6 @@ /obj/item/radio/intercom/directional/south, /turf/open/floor/iron, /area/station/science/explab) -"fRb" = ( -/obj/effect/turf_decal/trimline/neutral/filled/line{ - dir = 9 - }, -/obj/item/radio/intercom/directional/north, -/turf/open/floor/iron, -/area/station/hallway/secondary/service) "fRs" = ( /obj/effect/turf_decal/stripes/line{ dir = 10 @@ -20093,6 +20092,20 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/command/heads_quarters/qm) +"gbZ" = ( +/obj/effect/turf_decal/trimline/purple/filled/line{ + dir = 1 + }, +/obj/machinery/camera/directional/north{ + c_tag = "Science - Research & Development"; + network = list("ss13","rd") + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/item/kirbyplants/organic/plant10, +/turf/open/floor/iron/white, +/area/station/science/lab) "gcp" = ( /turf/closed/wall/r_wall, /area/station/commons/vacant_room) @@ -22957,13 +22970,6 @@ "hhc" = ( /turf/open/floor/iron/dark, /area/station/command/bridge) -"hhf" = ( -/obj/machinery/power/smes{ - charge = 5e+06 - }, -/obj/structure/cable, -/turf/open/floor/circuit, -/area/station/ai_monitored/turret_protected/ai) "hht" = ( /obj/effect/landmark/event_spawn, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -23161,6 +23167,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/checker, /area/station/commons/lounge) +"hjz" = ( +/obj/effect/turf_decal/siding/white{ + dir = 1 + }, +/obj/machinery/modular_computer/preset/cargochat/medical{ + dir = 1 + }, +/turf/open/floor/iron/dark, +/area/station/medical/storage) "hjM" = ( /obj/structure/railing/corner{ dir = 4 @@ -25712,6 +25727,18 @@ }, /turf/open/floor/carpet, /area/station/service/chapel/monastery) +"ikM" = ( +/obj/structure/cable, +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 8 + }, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/white, +/area/station/medical/medbay/central) "ikT" = ( /obj/effect/turf_decal/trimline/dark_red/warning{ dir = 10 @@ -26539,6 +26566,19 @@ }, /turf/open/floor/iron, /area/station/cargo/miningdock) +"iBo" = ( +/obj/machinery/camera/directional/north{ + c_tag = "Service - Autolathe Room" + }, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/light/dim/directional/north, +/obj/structure/table, +/obj/machinery/fax{ + fax_name = "Service Hallway"; + name = "Service Fax Machine" + }, +/turf/open/floor/iron, +/area/station/hallway/secondary/service) "iBx" = ( /obj/effect/turf_decal/trimline/purple/filled/line{ dir = 1 @@ -27794,6 +27834,14 @@ }, /turf/open/floor/plating/airless, /area/station/asteroid) +"iYO" = ( +/obj/effect/turf_decal/trimline/purple/filled/line{ + dir = 1 + }, +/obj/machinery/newscaster/directional/north, +/obj/machinery/modular_computer/preset/cargochat/science, +/turf/open/floor/iron/white, +/area/station/science/lab) "iZb" = ( /turf/closed/wall, /area/station/security/office) @@ -31330,6 +31378,16 @@ /obj/effect/mapping_helpers/airlock/locked, /turf/open/floor/catwalk_floor, /area/station/maintenance/tram/mid) +"kfH" = ( +/obj/structure/railing{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 4 + }, +/obj/machinery/photobooth/security, +/turf/open/floor/iron, +/area/station/security/execution/transfer) "kfO" = ( /turf/open/floor/plating, /area/station/cargo/drone_bay) @@ -33908,6 +33966,13 @@ }, /turf/open/space/openspace, /area/station/solars/port) +"kXq" = ( +/obj/structure/cable/multilayer/multiz, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plating, +/area/station/ai_monitored/turret_protected/ai) "kXr" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -34662,6 +34727,11 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/construction/engineering) +"llW" = ( +/obj/machinery/power/smes/full, +/obj/structure/cable, +/turf/open/floor/circuit, +/area/station/ai_monitored/turret_protected/ai) "lml" = ( /turf/closed/wall/r_wall, /area/station/engineering/atmos/pumproom) @@ -37150,18 +37220,6 @@ "mbJ" = ( /turf/closed/wall, /area/station/maintenance/tram/right) -"mbK" = ( -/obj/structure/cable, -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 8 - }, -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/white, -/area/station/medical/medbay/central) "mbQ" = ( /obj/effect/turf_decal/trimline/brown/filled/line{ dir = 4 @@ -37232,17 +37290,6 @@ }, /turf/open/floor/plating, /area/station/command/heads_quarters/rd) -"mdk" = ( -/obj/effect/turf_decal/trimline/brown/filled/line{ - dir = 5 - }, -/obj/effect/turf_decal/trimline/yellow/filled/warning{ - dir = 5 - }, -/obj/structure/cable, -/obj/structure/table, -/turf/open/floor/iron, -/area/station/engineering/break_room) "mdl" = ( /obj/effect/turf_decal/trimline/white/warning{ dir = 6 @@ -37628,25 +37675,6 @@ /obj/machinery/newscaster/directional/north, /turf/open/floor/iron, /area/station/commons/fitness/recreation) -"mjy" = ( -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 9 - }, -/obj/machinery/status_display/evac/directional/west, -/obj/effect/turf_decal/trimline/red/filled/warning{ - dir = 4 - }, -/obj/structure/table, -/obj/item/paper_bin{ - pixel_x = -3; - pixel_y = 7 - }, -/obj/item/pen{ - pixel_x = 3; - pixel_y = 8 - }, -/turf/open/floor/iron, -/area/station/security/office) "mjF" = ( /obj/structure/disposalpipe/sorting/mail/flip{ dir = 4 @@ -38874,11 +38902,6 @@ /obj/structure/railing, /turf/open/floor/iron/dark, /area/station/command/heads_quarters/hop) -"mHZ" = ( -/obj/item/radio/intercom/directional/east, -/obj/machinery/photobooth, -/turf/open/floor/iron/grimy, -/area/station/service/library/lounge) "mId" = ( /obj/effect/turf_decal/trimline/green/filled/line, /obj/effect/turf_decal/trimline/green/filled/line{ @@ -39212,6 +39235,13 @@ /obj/machinery/light/directional/west, /turf/open/floor/iron/white, /area/station/medical/treatment_center) +"mOq" = ( +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 9 + }, +/obj/item/radio/intercom/directional/north, +/turf/open/floor/iron, +/area/station/hallway/secondary/service) "mOB" = ( /obj/structure/table, /obj/item/analyzer, @@ -42013,6 +42043,11 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron, /area/station/engineering/engine_smes) +"nOB" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/reagent_dispensers/watertank, +/turf/open/floor/iron, +/area/station/hallway/secondary/service) "nOI" = ( /obj/machinery/power/apc/auto_name/directional/south, /obj/structure/disposalpipe/segment{ @@ -43829,6 +43864,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/grass, /area/station/medical/virology) +"oxe" = ( +/mob/living/basic/slime, +/turf/open/floor/engine, +/area/station/science/xenobiology) "oxf" = ( /obj/structure/railing, /obj/effect/turf_decal/trimline/dark_blue/arrow_cw, @@ -44705,6 +44744,25 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/commons/storage/primary) +"oSu" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 9 + }, +/obj/machinery/status_display/evac/directional/west, +/obj/effect/turf_decal/trimline/red/filled/warning{ + dir = 4 + }, +/obj/structure/table, +/obj/item/paper_bin{ + pixel_x = -3; + pixel_y = 7 + }, +/obj/item/pen{ + pixel_x = 3; + pixel_y = 8 + }, +/turf/open/floor/iron, +/area/station/security/office) "oSB" = ( /obj/machinery/camera/directional/west{ network = list("ss13","Security","cargo"); @@ -46707,15 +46765,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/sorting) -"pBU" = ( -/obj/structure/railing{ - dir = 8 - }, -/obj/machinery/door/firedoor/border_only{ - dir = 8 - }, -/turf/open/floor/glass/reinforced, -/area/station/science/research) "pBZ" = ( /obj/structure/railing/corner{ dir = 4 @@ -47471,20 +47520,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/commons/storage/primary) -"pOY" = ( -/obj/effect/turf_decal/trimline/purple/filled/line{ - dir = 1 - }, -/obj/machinery/camera/directional/north{ - c_tag = "Science - Research & Development"; - network = list("ss13","rd") - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/item/kirbyplants/organic/plant10, -/turf/open/floor/iron/white, -/area/station/science/lab) "pOZ" = ( /obj/machinery/portable_atmospherics/scrubber, /obj/effect/turf_decal/trimline/red/filled/line{ @@ -48979,11 +49014,6 @@ /obj/effect/spawner/structure/window, /turf/open/floor/plating, /area/station/commons/fitness/recreation) -"qqm" = ( -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/structure/reagent_dispensers/watertank, -/turf/open/floor/iron, -/area/station/hallway/secondary/service) "qqv" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/on, /obj/machinery/light/directional/north, @@ -49258,21 +49288,23 @@ }, /turf/open/floor/iron, /area/station/command/bridge) -"qvR" = ( -/obj/structure/railing{ - dir = 4 - }, -/obj/machinery/door/firedoor/border_only{ - dir = 4 - }, -/turf/open/floor/glass/reinforced, -/area/station/science/research) "qvV" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 8 }, /turf/open/floor/iron, /area/station/security/prison/work) +"qwn" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + dir = 5 + }, +/obj/effect/turf_decal/trimline/yellow/filled/warning{ + dir = 5 + }, +/obj/structure/cable, +/obj/structure/table, +/turf/open/floor/iron, +/area/station/engineering/break_room) "qwq" = ( /obj/structure/table/wood, /obj/item/radio/intercom, @@ -51907,6 +51939,15 @@ /obj/effect/mapping_helpers/airlock/unres, /turf/open/floor/catwalk_floor, /area/station/maintenance/starboard/central) +"rpq" = ( +/obj/structure/railing{ + dir = 4 + }, +/obj/machinery/door/firedoor/border_only{ + dir = 4 + }, +/turf/open/floor/glass/reinforced, +/area/station/science/research) "rpr" = ( /obj/effect/turf_decal/siding/thinplating/corner{ dir = 4 @@ -57000,15 +57041,6 @@ /obj/machinery/shower/directional/south, /turf/open/floor/iron/freezer, /area/station/commons/toilet) -"thm" = ( -/obj/effect/turf_decal/siding/white{ - dir = 1 - }, -/obj/machinery/modular_computer/preset/cargochat/medical{ - dir = 1 - }, -/turf/open/floor/iron/dark, -/area/station/medical/storage) "thG" = ( /obj/effect/turf_decal/trimline/red/filled/line, /obj/effect/turf_decal/trimline/red/filled/corner{ @@ -62777,19 +62809,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/security/checkpoint/medical) -"vbl" = ( -/obj/machinery/camera/directional/north{ - c_tag = "Service - Autolathe Room" - }, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/machinery/light/dim/directional/north, -/obj/structure/table, -/obj/machinery/fax{ - fax_name = "Service Hallway"; - name = "Service Fax Machine" - }, -/turf/open/floor/iron, -/area/station/hallway/secondary/service) "vbt" = ( /obj/machinery/computer/atmos_control/oxygen_tank{ atmos_chambers = list(o2ordance="Oxygen Supply") @@ -65292,13 +65311,6 @@ }, /turf/open/floor/plating, /area/station/construction/mining/aux_base) -"vTD" = ( -/obj/structure/cable/multilayer/multiz, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/iron/dark, -/area/station/ai_monitored/turret_protected/ai) "vTE" = ( /obj/machinery/camera{ dir = 9; @@ -66034,12 +66046,6 @@ /obj/structure/railing/corner, /turf/open/space/openspace, /area/station/solars/starboard/fore) -"whX" = ( -/obj/machinery/airalarm/directional/north, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/machinery/modular_computer/preset/cargochat/service, -/turf/open/floor/iron, -/area/station/hallway/secondary/service) "wid" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment, @@ -66913,14 +66919,6 @@ /obj/structure/sign/warning/electric_shock, /turf/closed/wall/r_wall, /area/station/maintenance/port/central) -"wzX" = ( -/obj/effect/turf_decal/trimline/purple/filled/line{ - dir = 1 - }, -/obj/machinery/newscaster/directional/north, -/obj/machinery/modular_computer/preset/cargochat/science, -/turf/open/floor/iron/white, -/area/station/science/lab) "wAa" = ( /obj/effect/turf_decal/trimline/purple/filled/line{ dir = 4 @@ -86737,7 +86735,7 @@ jWs jvE eLB abU -aci +kfH acv acH sXc @@ -102685,10 +102683,10 @@ apl iRL snQ iRL -whX +bNI tbm nNZ -qqm +nOB cWZ klk kNo @@ -103199,7 +103197,7 @@ bje iRL snQ iRL -fRb +mOq twg dWn cWZ @@ -103752,7 +103750,7 @@ ixT gYI cgR ial -mdk +qwn amV mvy iXQ @@ -103970,7 +103968,7 @@ aeF iRL quF iRL -vbl +iBo sWF iog cWZ @@ -115592,7 +115590,7 @@ dUT gdC qVr bfH -dfC +oxe ahk hdA mBm @@ -115604,7 +115602,7 @@ hik sml bfH bfH -dfC +oxe jTC qVr aaa @@ -118676,7 +118674,7 @@ hFH tYB qVr jTC -dfC +oxe bfH bfH nbI @@ -118688,7 +118686,7 @@ rbU uAF ahk hdA -dfC +oxe bfH qVr aaa @@ -152593,7 +152591,7 @@ cSr rAS xzI uYa -mHZ +aUc ppK rAS rAS @@ -156634,7 +156632,7 @@ dEv ukw pyF dEv -mjy +oSu rWT gYd isV @@ -166203,7 +166201,7 @@ kZD wAe glU jSc -thm +hjz xRx aLw pVk @@ -167228,7 +167226,7 @@ jAc kkd qNI mrC -mbK +ikM tOw kGa djz @@ -182133,14 +182131,14 @@ wxu yjY eYS oxL -pOY +gbZ oGO xQN mEt vNk kTU xyt -qvR +rpq ovC dCq uiV @@ -183161,14 +183159,14 @@ aIv aHQ tJz oxL -wzX +iYO lpC vTb vTb rbn crj wWT -pBU +bCx uvB rBb tbK @@ -185803,7 +185801,7 @@ jLx ffe mgi pIQ -hhf +llW xZx rSB dVM @@ -186316,7 +186314,7 @@ mYB njC aoh iUO -vTD +kXq lxi njC mEb diff --git a/code/__DEFINES/_flags.dm b/code/__DEFINES/_flags.dm index 2166ae82bf7..cdad8bba52a 100644 --- a/code/__DEFINES/_flags.dm +++ b/code/__DEFINES/_flags.dm @@ -120,7 +120,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define UNIQUE_AREA (1<<8) /// If people are allowed to suicide in it. Mostly for OOC stuff like minigames #define BLOCK_SUICIDE (1<<9) -/// Can the Xenobio management console transverse this area by default? +/// If set, this area will be innately traversable by Xenobiology camera consoles. #define XENOBIOLOGY_COMPATIBLE (1<<10) /// If Abductors are unable to teleport in with their observation console #define ABDUCTOR_PROOF (1<<11) diff --git a/code/__DEFINES/_protect.dm b/code/__DEFINES/_protect.dm index 9152cfcb570..a1202ebaf32 100644 --- a/code/__DEFINES/_protect.dm +++ b/code/__DEFINES/_protect.dm @@ -11,7 +11,7 @@ return FALSE;\ }\ ##Path/Read(savefile/savefile){\ - qdel(src);\ + del(src);\ }\ ##Path/Write(savefile/savefile){\ return;\ @@ -19,3 +19,4 @@ #else #define GENERAL_PROTECT_DATUM(Path) #endif +// we del instead of qdel because for security reasons we must ensure the datum does not exist if Read is called. qdel will not enforce this. diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 9946e022b61..a0ab44002a0 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -26,6 +26,8 @@ #define BANTYPE_ANY_JOB 9 //Admin Permissions +/// Used for signifying that all admins can use this regardless of actual permissions +#define R_NONE NONE #define R_BUILD (1<<0) #define R_ADMIN (1<<1) #define R_BAN (1<<2) @@ -177,4 +179,3 @@ GLOBAL_VAR_INIT(ghost_role_flags, ALL) /// Used in logging uses of admin verbs (and sometimes some non-admin or debug verbs) to the blackbox /// Only pass it a string key, the verb being used. #define BLACKBOX_LOG_ADMIN_VERB(the_verb) SSblackbox.record_feedback("tally", "admin_verb", 1, the_verb) - diff --git a/code/__DEFINES/admin_verb.dm b/code/__DEFINES/admin_verb.dm new file mode 100644 index 00000000000..cbf856bf436 --- /dev/null +++ b/code/__DEFINES/admin_verb.dm @@ -0,0 +1,92 @@ +/client/CanProcCall(procname) + if(findtext(procname, "__avd_") == 1) + message_admins("[key_name_admin(usr)] attempted to directly call admin verb '[procname]'.") + log_admin("[key_name(usr)] attempted to directly call admin verb '[procname]'.") + return FALSE + return ..() + +/** + * This is the only macro you should use to define admin verbs. + * It will define the verb and the verb holder for you. + * Using it is very simple: + * ADMIN_VERB(verb_path, R_PERM, "Name", "Description", "Admin.Category", args...) + * This sets up all of the above and also acts as syntatic sugar as a verb delcaration for the verb itself. + * Note that the verb args have an injected `client/user` argument that is the user that called the verb. + * Do not use usr in your verb; technically you can but I'll kill you. + */ +#define _ADMIN_VERB(verb_path_name, verb_permissions, verb_name, verb_desc, verb_category, show_in_context_menu, verb_args...) \ +/datum/admin_verb/##verb_path_name \ +{ \ + name = ##verb_name; \ + description = ##verb_desc; \ + category = ##verb_category; \ + permissions = ##verb_permissions; \ + verb_path = /client/proc/__avd_##verb_path_name; \ +}; \ +/client/proc/__avd_##verb_path_name(##verb_args) \ +{ \ + set name = ##verb_name; \ + set desc = ##verb_desc; \ + set hidden = FALSE; /* this is explicitly needed as the proc begins with an underscore */ \ + set popup_menu = ##show_in_context_menu; \ + set category = ##verb_category; \ + var/list/_verb_args = list(usr, /datum/admin_verb/##verb_path_name); \ + _verb_args += args; \ + SSadmin_verbs.dynamic_invoke_verb(arglist(_verb_args)); \ +}; \ +/datum/admin_verb/##verb_path_name/__avd_do_verb(client/user, ##verb_args) + +#define ADMIN_VERB(verb_path_name, verb_permissions, verb_name, verb_desc, verb_category, verb_args...) \ +_ADMIN_VERB(verb_path_name, verb_permissions, verb_name, verb_desc, verb_category, FALSE, ##verb_args) + +#define ADMIN_VERB_ONLY_CONTEXT_MENU(verb_path_name, verb_permissions, verb_name, verb_args...) \ +_ADMIN_VERB(verb_path_name, verb_permissions, verb_name, ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, TRUE, ##verb_args) + +#define ADMIN_VERB_AND_CONTEXT_MENU(verb_path_name, verb_permissions, verb_name, verb_desc, verb_category, verb_args...) \ +_ADMIN_VERB(verb_path_name, verb_permissions, verb_name, verb_desc, verb_category, TRUE, ##verb_args) + +/// Used to define a special check to determine if the admin verb should exist at all. Useful for verbs such as play sound which require configuration. +#define ADMIN_VERB_CUSTOM_EXIST_CHECK(verb_path_name) \ +/datum/admin_verb/##verb_path_name/__avd_check_should_exist() + +/// Used to define the visibility flag of the verb. If the admin does not have this flag enabled they will not see the verb. +#define ADMIN_VERB_VISIBILITY(verb_path_name, verb_visibility) /datum/admin_verb/##verb_path_name/visibility_flag = ##verb_visibility + +// These are put here to prevent the "procedure override precedes definition" error. +/datum/admin_verb/proc/__avd_get_verb_path() + CRASH("__avd_get_verb_path not defined. use the macro") +/datum/admin_verb/proc/__avd_do_verb(...) + CRASH("__avd_do_verb not defined. use the macro") +/datum/admin_verb/proc/__avd_check_should_exist() + return TRUE + +/* + * This is an example of how to use the above macro: + * ``` + * ADMIN_VERB(name_of_verb, R_ADMIN, "Verb Name", "Verb Desc", "Verb Category", mob/target in world) + * to_chat(user, "Hello!") + * ``` + * Note the implied `client/user` argument that is injected into the verb. + * Also note that byond is shit and you cannot multi-line the macro call. + */ + +/// Use this to mark your verb as not having a description. Should ONLY be used if you are also hiding the verb! +#define ADMIN_VERB_NO_DESCRIPTION "" +/// Used to verbs you do not want to show up in the master verb panel. +#define ADMIN_CATEGORY_HIDDEN null + +// Admin verb categories +#define ADMIN_CATEGORY_MAIN "Admin" +#define ADMIN_CATEGORY_EVENTS "Admin.Events" +#define ADMIN_CATEGORY_FUN "Admin.Fun" +#define ADMIN_CATEGORY_GAME "Admin.Game" + +// Special categories that are seperated +#define ADMIN_CATEGORY_DEBUG "Debug" +#define ADMIN_CATEGORY_SERVER "Server" +#define ADMIN_CATEGORY_OBJECT "Object" +#define ADMIN_CATEGORY_MAPPING "Mapping" +#define ADMIN_CATEGORY_PROFILE "Profile" + +// Visibility flags +#define ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG "Map-Debug" diff --git a/code/__DEFINES/arcades.dm b/code/__DEFINES/arcades.dm new file mode 100644 index 00000000000..fac3e8091d3 --- /dev/null +++ b/code/__DEFINES/arcades.dm @@ -0,0 +1,15 @@ +///Goes in the Weapon slot. +#define WEAPON_SLOT "Weapon" +///Goes in the Armor slot. +#define ARMOR_SLOT "Armor" + +//Worlds found in Battle Arcade +#define BATTLE_WORLD_ONE "The Plains" +#define BATTLE_WORLD_TWO "The Forest" +#define BATTLE_WORLD_THREE "The Mountains" +#define BATTLE_WORLD_FOUR "The Desert" +#define BATTLE_WORLD_FIVE "The Swamp" +#define BATTLE_WORLD_SIX "The Ocean" +#define BATTLE_WORLD_SEVEN "The Sky" +#define BATTLE_WORLD_EIGHT "The Moon" +#define BATTLE_WORLD_NINE "The Void" diff --git a/code/__DEFINES/area_editor.dm b/code/__DEFINES/area_editor.dm deleted file mode 100644 index f0ef57c7e52..00000000000 --- a/code/__DEFINES/area_editor.dm +++ /dev/null @@ -1,5 +0,0 @@ -// Used to edit areas. -#define AREA_ERRNONE 0 -#define AREA_STATION 1 -#define AREA_SPACE 2 -#define AREA_SPECIAL 3 diff --git a/code/__DEFINES/basic_mobs.dm b/code/__DEFINES/basic_mobs.dm index b673d0e7a12..c827f760b8a 100644 --- a/code/__DEFINES/basic_mobs.dm +++ b/code/__DEFINES/basic_mobs.dm @@ -14,6 +14,8 @@ #define IMMUNE_TO_FISTS (1<<4) /// Mob is immune to getting wet #define IMMUNE_TO_GETTING_WET (1<<5) +/// Disables the function of attacking random body zones +#define PRECISE_ATTACK_ZONES (1<<6) /// Temporary trait applied when an attack forecast animation has completed #define TRAIT_BASIC_ATTACK_FORECAST "trait_basic_attack_forecast" diff --git a/code/__DEFINES/click.dm b/code/__DEFINES/click.dm new file mode 100644 index 00000000000..5900dd54210 --- /dev/null +++ b/code/__DEFINES/click.dm @@ -0,0 +1,8 @@ +/// Action has succeeded, preventing further alt click interaction +#define CLICK_ACTION_SUCCESS (1<<0) +/// Action failed, preventing further alt click interaction +#define CLICK_ACTION_BLOCKING (1<<1) +/// Either return state +#define CLICK_ACTION_ANY (CLICK_ACTION_SUCCESS | CLICK_ACTION_BLOCKING) + +/// Use NONE for continue interaction diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 847fd52cc22..686e422b020 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -282,6 +282,8 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( #define BODY_ZONE_L_LEG "l_leg" #define BODY_ZONE_R_LEG "r_leg" +GLOBAL_LIST_INIT(all_body_zones, list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)) +GLOBAL_LIST_INIT(limb_zones, list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)) GLOBAL_LIST_INIT(arm_zones, list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) #define BODY_ZONE_PRECISE_EYES "eyes" diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm index 24524395f35..f4dcd496641 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm @@ -12,10 +12,9 @@ ///from base of atom/get_examine_name(): (/mob, list/overrides) #define COMSIG_ATOM_GET_EXAMINE_NAME "atom_examine_name" //Positions for overrides list - #define EXAMINE_POSITION_ARTICLE (1<<0) - #define EXAMINE_POSITION_BEFORE (1<<1) - //End positions - #define COMPONENT_EXNAME_CHANGED (1<<0) + #define EXAMINE_POSITION_ARTICLE 1 + #define EXAMINE_POSITION_BEFORE 2 + #define EXAMINE_POSITION_NAME 3 ///from base of atom/examine(): (/mob, list/examine_text, can_see_inside) #define COMSIG_ATOM_REAGENT_EXAMINE "atom_reagent_examine" /// Stop the generic reagent examine text diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_mouse.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_mouse.dm index 3ff131d9a39..2ea2e4d5fe3 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_mouse.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_mouse.dm @@ -13,7 +13,6 @@ #define COMSIG_CLICK_CTRL "ctrl_click" ///from base of atom/AltClick(): (/mob) #define COMSIG_CLICK_ALT "alt_click" - #define COMPONENT_CANCEL_CLICK_ALT (1<<0) ///from base of atom/alt_click_secondary(): (/mob) #define COMSIG_CLICK_ALT_SECONDARY "alt_click_secondary" #define COMPONENT_CANCEL_CLICK_ALT_SECONDARY (1<<0) diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm index 068aadf6a5e..f33d2f1f40d 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -182,8 +182,6 @@ #define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" ///from base of obj/item/afterattack_secondary(): (atom/target, obj/item/weapon, proximity_flag, click_parameters) #define COMSIG_MOB_ITEM_AFTERATTACK_SECONDARY "mob_item_afterattack_secondary" -///from base of obj/item/attack_qdeleted(): (atom/target, mob/user, proximity_flag, click_parameters) -#define COMSIG_MOB_ITEM_ATTACK_QDELETED "mob_item_attack_qdeleted" ///from base of mob/RangedAttack(): (atom/A, modifiers) #define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged" ///from base of mob/ranged_secondary_attack(): (atom/target, modifiers) diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index 01145cd32ea..43e3a09a028 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -472,8 +472,6 @@ #define COMPONENT_AFTERATTACK_PROCESSED_ITEM (1<<0) ///from base of obj/item/afterattack_secondary(): (atom/target, mob/user, proximity_flag, click_parameters) #define COMSIG_ITEM_AFTERATTACK_SECONDARY "item_afterattack_secondary" -///from base of obj/item/attack_qdeleted(): (atom/target, mob/user, params) -#define COMSIG_ITEM_ATTACK_QDELETED "item_attack_qdeleted" ///from base of obj/item/embedded(): (atom/target, obj/item/bodypart/part) #define COMSIG_ITEM_EMBEDDED "item_embedded" ///from base of datum/component/embedded/safeRemove(): (mob/living/carbon/victim) @@ -529,3 +527,8 @@ /// from /datum/component/dart_insert/on_reskin() #define COMSIG_DART_INSERT_PARENT_RESKINNED "dart_insert_parent_reskinned" + +/// Sent from /obj/item/update_weight_class(). (old_w_class, new_w_class) +#define COMSIG_ITEM_WEIGHT_CLASS_CHANGED "item_weight_class_changed" +/// Sent from /obj/item/update_weight_class(), to it's loc. (obj/item/changed_item, old_w_class, new_w_class) +#define COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED "atom_contents_weight_class_changed" diff --git a/code/__DEFINES/explosions.dm b/code/__DEFINES/explosions.dm index a1645b659d1..dd9a74bbae3 100644 --- a/code/__DEFINES/explosions.dm +++ b/code/__DEFINES/explosions.dm @@ -52,6 +52,12 @@ #define EXARG_KEY_SILENT STRINGIFY(silent) /// Whether or not the explosion should produce smoke if it is large enough to warrant it. #define EXARG_KEY_SMOKE STRINGIFY(smoke) +/// Whether or not to leave the epicenter turf unaffected +#define EXARG_KEY_PROTECT_EPICENTER STRINGIFY(protect_epicenter) +/// For directional explosions, the angle the explosion is pointing at. +#define EXARG_KEY_EXPLOSION_DIRECTION STRINGIFY(explosion_direction) +/// For directional explosions, the angle covered by the explosion, centred on EXPLOSION_DIRECTION. +#define EXARG_KEY_EXPLOSION_ARC STRINGIFY(explosion_arc) // Explodable component deletion values /// Makes the explodable component queue to reset its exploding status when it detonates. diff --git a/code/__DEFINES/interaction_flags.dm b/code/__DEFINES/interaction_flags.dm index 55732f2364b..418466a0eb2 100644 --- a/code/__DEFINES/interaction_flags.dm +++ b/code/__DEFINES/interaction_flags.dm @@ -36,10 +36,7 @@ #define INTERACT_MACHINE_OPEN_SILICON (1<<4) /// must be silicon to interact #define INTERACT_MACHINE_REQUIRES_SILICON (1<<5) -/// This flag determines if a machine set_machine's the user when the user uses it, making updateUsrDialog make the user re-call interact() on it. -/// This is exclusively used for non-TGUI UIs, and its instances should be removed when moved to TGUI. -#define INTERACT_MACHINE_SET_MACHINE (1<<6) /// the user must have vision to interact (blind people need not apply) -#define INTERACT_MACHINE_REQUIRES_SIGHT (1<<7) +#define INTERACT_MACHINE_REQUIRES_SIGHT (1<<6) /// the user must be able to read to interact -#define INTERACT_MACHINE_REQUIRES_LITERACY (1<<8) +#define INTERACT_MACHINE_REQUIRES_LITERACY (1<<7) diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm index efcc3a4fbd8..6f1c9512b39 100644 --- a/code/__DEFINES/inventory.dm +++ b/code/__DEFINES/inventory.dm @@ -14,6 +14,9 @@ /// Essentially means it cannot be picked up or placed in an inventory, (e.g. mech parts, safe) #define WEIGHT_CLASS_GIGANTIC 6 +/// Weight class that can fit in pockets +#define POCKET_WEIGHT_CLASS WEIGHT_CLASS_SMALL + //Inventory depth: limits how many nested storage items you can access directly. //1: stuff in mob, 2: stuff in backpack, 3: stuff in box in backpack, etc #define INVENTORY_DEPTH 3 diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index d739b697dc3..357df07f901 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -857,6 +857,10 @@ GLOBAL_LIST_INIT(layers_to_offset, list( #define ALLOW_SILICON_REACH (1<<6) /// If resting on the floor is allowed to perform action (pAIs can play music while resting) #define ALLOW_RESTING (1<<7) +/// If this is accessible to creatures with ventcrawl capabilities +#define NEED_VENTCRAWL (1<<8) +/// Checks for base adjacency, but silences the error +#define SILENT_ADJACENCY (1<<9) /// The default mob sprite size (used for shrinking or enlarging the mob sprite to regular size) #define RESIZE_DEFAULT_SIZE 1 diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm index 469811c96dc..9e38eada923 100644 --- a/code/__DEFINES/obj_flags.dm +++ b/code/__DEFINES/obj_flags.dm @@ -2,20 +2,19 @@ #define EMAGGED (1<<0) -#define IN_USE (1<<1) // If we have a user using us, this will be set on. We will check if the user has stopped using us, and thus stop updating and LAGGING EVERYTHING! -#define CAN_BE_HIT (1<<2) //can this be bludgeoned by items? -#define DANGEROUS_POSSESSION (1<<3) //Admin possession yes/no -#define UNIQUE_RENAME (1<<4) // can you customize the description/name of the thing? -#define BLOCK_Z_OUT_DOWN (1<<5) // Should this object block z falling from loc? -#define BLOCK_Z_OUT_UP (1<<6) // Should this object block z uprise from loc? -#define BLOCK_Z_IN_DOWN (1<<7) // Should this object block z falling from above? -#define BLOCK_Z_IN_UP (1<<8) // Should this object block z uprise from below? -#define BLOCKS_CONSTRUCTION (1<<9) //! Does this object prevent things from being built on it? -#define BLOCKS_CONSTRUCTION_DIR (1<<10) //! Does this object prevent same-direction things from being built on it? -#define IGNORE_DENSITY (1<<11) //! Can we ignore density when building on this object? (for example, directional windows and grilles) -#define INFINITE_RESKIN (1<<12) // We can reskin this item infinitely -#define CONDUCTS_ELECTRICITY (1<<13) //! Can this object conduct electricity? -#define NO_DECONSTRUCTION (1<<14) //! Atoms don't spawn anything when deconstructed. They just vanish +#define CAN_BE_HIT (1<<1) //can this be bludgeoned by items? +#define DANGEROUS_POSSESSION (1<<2) //Admin possession yes/no +#define UNIQUE_RENAME (1<<3) // can you customize the description/name of the thing? +#define BLOCK_Z_OUT_DOWN (1<<4) // Should this object block z falling from loc? +#define BLOCK_Z_OUT_UP (1<<5) // Should this object block z uprise from loc? +#define BLOCK_Z_IN_DOWN (1<<6) // Should this object block z falling from above? +#define BLOCK_Z_IN_UP (1<<7) // Should this object block z uprise from below? +#define BLOCKS_CONSTRUCTION (1<<8) //! Does this object prevent things from being built on it? +#define BLOCKS_CONSTRUCTION_DIR (1<<9) //! Does this object prevent same-direction things from being built on it? +#define IGNORE_DENSITY (1<<10) //! Can we ignore density when building on this object? (for example, directional windows and grilles) +#define INFINITE_RESKIN (1<<11) // We can reskin this item infinitely +#define CONDUCTS_ELECTRICITY (1<<12) //! Can this object conduct electricity? +#define NO_DEBRIS_AFTER_DECONSTRUCTION (1<<13) //! Atoms don't spawn anything when deconstructed. They just vanish // If you add new ones, be sure to add them to /obj/Initialize as well for complete mapping support diff --git a/code/__DEFINES/research/anomalies.dm b/code/__DEFINES/research/anomalies.dm index 29c05d20919..17c93120511 100644 --- a/code/__DEFINES/research/anomalies.dm +++ b/code/__DEFINES/research/anomalies.dm @@ -39,10 +39,13 @@ GLOBAL_LIST_INIT(bioscrambler_organs_blacklist, typecacheof(list ( /obj/item/organ/internal/brain, /obj/item/organ/internal/body_egg, /obj/item/organ/internal/cyberimp, + /obj/item/organ/internal/ears/dullahan, + /obj/item/organ/internal/eyes/dullahan, /obj/item/organ/internal/heart/cursed, /obj/item/organ/internal/heart/demon, /obj/item/organ/internal/lungs, /obj/item/organ/internal/monster_core, + /obj/item/organ/internal/tongue/dullahan, /obj/item/organ/internal/vocal_cords/colossus, /obj/item/organ/internal/zombie_infection, /obj/item/organ/internal/empowered_borer_egg, // SKYRAT EDIT ADDITION diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm index 3260dd4d5a8..f82f4af2ddd 100644 --- a/code/__DEFINES/say.dm +++ b/code/__DEFINES/say.dm @@ -111,6 +111,7 @@ #define MAX_CHARTER_LEN 80 #define MAX_PLAQUE_LEN 144 #define MAX_LABEL_LEN 64 +#define MAX_DESC_LEN 280 // Audio/Visual Flags. Used to determine what sense are required to notice a message. #define MSG_VISUAL (1<<0) diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 1a1940b76cd..d7ec3e4669c 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -136,8 +136,9 @@ #define INIT_ORDER_DBCORE 95 #define INIT_ORDER_BLACKBOX 94 #define INIT_ORDER_SERVER_MAINT 93 +#define INIT_ORDER_PLAYER_RANKS 86 // SKYRAT EDIT - Player Ranks Subsystem #define INIT_ORDER_INPUT 85 -#define INIT_ORDER_PLAYER_RANKS 84 // SKYRAT EDIT - Player Ranks Subsystem +#define INIT_ORDER_ADMIN_VERBS 84 // needs to be pretty high, admins cant do much without it #define INIT_ORDER_SOUNDS 83 #define INIT_ORDER_INSTRUMENTS 82 #define INIT_ORDER_GREYSCALE 81 @@ -190,6 +191,7 @@ #define INIT_ORDER_MATURITY_GUARD -60 //SKYRAT EDIT ADDITION #define INIT_ORDER_DECAY -61 //SKYRAT EDIT ADDITION #define INIT_ORDER_EXPLOSIONS -69 +#define INIT_ORDER_LOOT -70 #define INIT_ORDER_STATPANELS -97 #define INIT_ORDER_BAN_CACHE -98 #define INIT_ORDER_INIT_PROFILER -99 //Near the end, logs the costs of initialize diff --git a/code/__DEFINES/text.dm b/code/__DEFINES/text.dm index 5dac5df883d..7761587170e 100644 --- a/code/__DEFINES/text.dm +++ b/code/__DEFINES/text.dm @@ -64,6 +64,10 @@ */ #define PREVENT_CHARACTER_TRIM_LOSS(integer) (integer + 1) +/// BYOND's string procs don't support being used on datum references (as in it doesn't look for a name for stringification) +/// We just use this macro to ensure that we will only pass strings to this BYOND-level function without developers needing to really worry about it. +#define LOWER_TEXT(thing) lowertext(UNLINT("[thing]")) + /// Folder directory for strings #define STRING_DIRECTORY "strings" diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index e42bd5dd559..f1335f8ff58 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -589,6 +589,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_BRAINWASHING "brainwashing" /// Allows chef's to chefs kiss their food, to make them with love #define TRAIT_CHEF_KISS "chefs_kiss" +/// Allows clowns to bend balloons into animals +#define TRAIT_BALLOON_SUTRA "balloon_sutra" ///Movement type traits for movables. See elements/movetype_handler.dm #define TRAIT_MOVE_GROUND "move_ground" @@ -735,6 +737,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai //quirk traits #define TRAIT_ALCOHOL_TOLERANCE "alcohol_tolerance" +#define TRAIT_ANOSMIA "anosmia" #define TRAIT_HEAVY_DRINKER "heavy_drinker" #define TRAIT_AGEUSIA "ageusia" #define TRAIT_HEAVY_SLEEPER "heavy_sleeper" @@ -766,6 +769,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_POSTERBOY "poster_boy" #define TRAIT_THROWINGARM "throwing_arm" #define TRAIT_SETTLER "settler" +#define TRAIT_STRONG_STOMACH "strong_stomach" /// This mob always lands on their feet when they fall, for better or for worse. #define TRAIT_CATLIKE_GRACE "catlike_grace" @@ -812,6 +816,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai ///Trait applied to turfs when an atmos holosign is placed on them. It will stop firedoors from closing. #define TRAIT_FIREDOOR_STOP "firedoor_stop" +///Trait applied to turf blocked by a containment field +#define TRAIT_CONTAINMENT_FIELD "containment_field" + /// Trait applied when the MMI component is added to an [/obj/item/integrated_circuit] #define TRAIT_COMPONENT_MMI "component_mmi" diff --git a/code/__DEFINES/traits/sources.dm b/code/__DEFINES/traits/sources.dm index dcbfab7fe5f..56bcbf3c90d 100644 --- a/code/__DEFINES/traits/sources.dm +++ b/code/__DEFINES/traits/sources.dm @@ -286,8 +286,8 @@ /// Trait from an organ being inside a bodypart #define ORGAN_INSIDE_BODY_TRAIT "organ_inside_body" -/// Trait when something was labelled by a pen. -#define PEN_LABEL_TRAIT "pen_label" +/// Trait when something was labelled by the /datum/element/tool_renaming element. +#define RENAMING_TOOL_LABEL_TRAIT "renaming_tool_label" /// Trait when a drink was renamed by a shaker #define SHAKER_LABEL_TRAIT "shaker_trait" diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm index dfa930f7a76..a83ef71ddc6 100644 --- a/code/__DEFINES/vv.dm +++ b/code/__DEFINES/vv.dm @@ -136,6 +136,7 @@ // /mob/living #define VV_HK_GIVE_SPEECH_IMPEDIMENT "impede_speech" +#define VV_HK_ADMIN_RENAME "admin_rename" #define VV_HK_ADD_MOOD "addmood" #define VV_HK_REMOVE_MOOD "removemood" #define VV_HK_GIVE_HALLUCINATION "give_hallucination" diff --git a/code/__DEFINES/~skyrat_defines/combat.dm b/code/__DEFINES/~skyrat_defines/combat.dm index 28a21fae9b3..86d8e40d57f 100644 --- a/code/__DEFINES/~skyrat_defines/combat.dm +++ b/code/__DEFINES/~skyrat_defines/combat.dm @@ -59,14 +59,13 @@ #define HEADSMASH_BLOCK_ARMOR 20 #define SUPLEX_TIMER 3 SECONDS -/// Skyrat change - alt-clicking a human as another human while grappling them tightly makes you try for grappling-based maneuvers. -/mob/living/carbon/human/AltClick(mob/user) +// alt-clicking a human as another human while grappling them tightly makes you try for grappling-based maneuvers. +/mob/living/carbon/human/click_alt(mob/user) if(!ishuman(user)) return ..() var/mob/living/carbon/human/human_user = user if(human_user == src || !human_user.combat_mode || !human_user.dna.species.try_grab_maneuver(user, src)) - return FALSE - . = ..() + return CLICK_ACTION_BLOCKING /// State check for grab maneuver - because you can't logically suplex a man if you've stopped grappling them. /datum/species/proc/grab_maneuver_state_check(mob/living/carbon/human/user, mob/living/carbon/human/target) diff --git a/code/__HELPERS/areas.dm b/code/__HELPERS/areas.dm index 8df182c90d0..dc2f66c2ed0 100644 --- a/code/__HELPERS/areas.dm +++ b/code/__HELPERS/areas.dm @@ -293,3 +293,51 @@ GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(list( mobs_in_area += mob break return mobs_in_area + +/** + * rename_area + * Renames an area to the given new name, updating all machines' names and firedoors + * to properly ensure alarms and machines are named correctly at all times. + * Args: + * - area_to_rename: The area that's being renamed. + * - new_name: The name we're changing said area to. + */ +/proc/rename_area(area/area_to_rename, new_name) + var/prevname = "[area_to_rename.name]" + set_area_machinery_title(area_to_rename, new_name, prevname) + area_to_rename.name = new_name + require_area_resort() //area renamed so resort the names + + if(LAZYLEN(area_to_rename.firedoors)) + for(var/obj/machinery/door/firedoor/area_firedoors as anything in area_to_rename.firedoors) + area_firedoors.CalculateAffectingAreas() + area_to_rename.update_areasize() + return TRUE + +/** + * Renames all machines in a defined area from the old title to the new title. + * Used when renaming an area to ensure that all machiens are labeled the new area's machine. + * Args: + * - area_renaming: The area being renamed, which we'll check turfs from to rename machines in. + * - title: The new name of the area that we're swapping into. + * - oldtitle: The old name of the area that we're replacing text from. + */ +/proc/set_area_machinery_title(area/area_renaming, title, oldtitle) + if(!oldtitle) // or replacetext goes to infinite loop + return + + //stuff tied to the area to rename + var/static/list/to_rename = typecacheof(list( + /obj/machinery/airalarm, + /obj/machinery/atmospherics/components/unary/vent_scrubber, + /obj/machinery/atmospherics/components/unary/vent_pump, + /obj/machinery/door, + /obj/machinery/firealarm, + /obj/machinery/light_switch, + /obj/machinery/power/apc, + /obj/machinery/camera, + )) + for(var/list/zlevel_turfs as anything in area_renaming.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + for(var/obj/machine as anything in typecache_filter_list(area_turf.contents, to_rename)) + machine.name = replacetext(machine.name, oldtitle, title) diff --git a/code/__HELPERS/atmospherics.dm b/code/__HELPERS/atmospherics.dm index 3ac3bfaed56..2a59cf60b40 100644 --- a/code/__HELPERS/atmospherics.dm +++ b/code/__HELPERS/atmospherics.dm @@ -105,7 +105,7 @@ GLOBAL_LIST_EMPTY(gas_handbook) factor_info["factor_name"] = factor factor_info["factor_type"] = "misc" if(factor == "Temperature" || factor == "Pressure") - factor_info["tooltip"] = "Reaction is influenced by the [lowertext(factor)] of the place where the reaction is occuring." + factor_info["tooltip"] = "Reaction is influenced by the [LOWER_TEXT(factor)] of the place where the reaction is occuring." else if(factor == "Energy") factor_info["tooltip"] = "Energy released by the reaction, may or may not result in linear temperature change depending on a slew of other factors." else if(factor == "Radiation") @@ -138,7 +138,7 @@ GLOBAL_LIST_EMPTY(gas_handbook) factor_info["factor_name"] = factor factor_info["factor_type"] = "misc" if(factor == "Temperature" || factor == "Pressure") - factor_info["tooltip"] = "Reaction is influenced by the [lowertext(factor)] of the place where the reaction is occuring." + factor_info["tooltip"] = "Reaction is influenced by the [LOWER_TEXT(factor)] of the place where the reaction is occuring." else if(factor == "Energy") factor_info["tooltip"] = "Energy released by the reaction, may or may not result in linear temperature change depending on a slew of other factors." else if(factor == "Radiation") diff --git a/code/__HELPERS/chat_filter.dm b/code/__HELPERS/chat_filter.dm index 34d811bf85b..22fe36a2136 100644 --- a/code/__HELPERS/chat_filter.dm +++ b/code/__HELPERS/chat_filter.dm @@ -1,6 +1,6 @@ // [2] is the group index of the blocked term when it is not using word bounds. // This is sanity checked by unit tests. -#define GET_MATCHED_GROUP(regex) (lowertext(regex.group[2] || regex.match)) +#define GET_MATCHED_GROUP(regex) (LOWER_TEXT(regex.group[2] || regex.match)) /// Given a text, will return what word is on the IC filter, with the reason. /// Returns null if the message is OK. diff --git a/code/__HELPERS/hallucinations.dm b/code/__HELPERS/hallucinations.dm index 525114cea28..1eeab08d876 100644 --- a/code/__HELPERS/hallucinations.dm +++ b/code/__HELPERS/hallucinations.dm @@ -113,11 +113,7 @@ GLOBAL_LIST_INIT(random_hallucination_weighted_list, generate_hallucination_weig to_chat(usr, span_boldnotice("The total weight of the hallucination weighted list is [total_weight].")) return total_weight -/// Debug verb for getting the weight of each distinct type within the random_hallucination_weighted_list -/client/proc/debug_hallucination_weighted_list_per_type() - set name = "Show Hallucination Weights" - set category = "Debug" - +ADMIN_VERB(debug_hallucination_weighted_list_per_type, R_DEBUG, "Show Hallucination Weights", "View the weight of each hallucination subtype in the random weighted list.", ADMIN_CATEGORY_DEBUG) var/header = "Type Weight Percent" var/total_weight = debug_hallucination_weighted_list() @@ -153,7 +149,7 @@ GLOBAL_LIST_INIT(random_hallucination_weighted_list, generate_hallucination_weig var/page_style = "" var/page_contents = "[page_style][header][jointext(assoc_to_keys(all_weights), "")]
" - var/datum/browser/popup = new(mob, "hallucinationdebug", "Hallucination Weights", 600, 400) + var/datum/browser/popup = new(user.mob, "hallucinationdebug", "Hallucination Weights", 600, 400) popup.set_content(page_contents) popup.open() diff --git a/code/__HELPERS/hearted.dm b/code/__HELPERS/hearted.dm index 1eafef56a4f..adae298516e 100644 --- a/code/__HELPERS/hearted.dm +++ b/code/__HELPERS/hearted.dm @@ -54,7 +54,7 @@ if(!heart_nominee) return - heart_nominee = lowertext(heart_nominee) + heart_nominee = LOWER_TEXT(heart_nominee) var/list/name_checks = get_mob_by_name(heart_nominee) if(!name_checks || name_checks.len == 0) query_heart(attempt + 1) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 6ab82d1584c..fd11d8f0651 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -679,7 +679,7 @@ world if(uppercase == 1) letter = uppertext(letter) else if(uppercase == -1) - letter = lowertext(letter) + letter = LOWER_TEXT(letter) var/image/text_image = new(loc = A) text_image.maptext = MAPTEXT("[letter]") diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm index 33bb0348df5..12c34d3a705 100644 --- a/code/__HELPERS/names.dm +++ b/code/__HELPERS/names.dm @@ -215,22 +215,22 @@ GLOBAL_DATUM(syndicate_code_response_regex, /regex) if(2) switch(rand(1,3))//Food, drinks, or places. Only selectable once. if(1) - . += lowertext(pick(drinks)) + . += LOWER_TEXT(pick(drinks)) if(2) - . += lowertext(pick(foods)) + . += LOWER_TEXT(pick(foods)) if(3) - . += lowertext(pick(locations)) + . += LOWER_TEXT(pick(locations)) safety -= 2 if(3) switch(rand(1,4))//Abstract nouns, objects, adjectives, threats. Can be selected more than once. if(1) - . += lowertext(pick(nouns)) + . += LOWER_TEXT(pick(nouns)) if(2) - . += lowertext(pick(objects)) + . += LOWER_TEXT(pick(objects)) if(3) - . += lowertext(pick(adjectives)) + . += LOWER_TEXT(pick(adjectives)) if(4) - . += lowertext(pick(threats)) + . += LOWER_TEXT(pick(threats)) if(!return_list) if(words == 1) . += "." diff --git a/code/__HELPERS/reagents.dm b/code/__HELPERS/reagents.dm index d557db3173a..012a1fd5cc0 100644 --- a/code/__HELPERS/reagents.dm +++ b/code/__HELPERS/reagents.dm @@ -155,7 +155,7 @@ ///Returns a list of chemical_reaction datums that have the input STRING as a product /proc/get_reagent_type_from_product_string(string) - var/input_reagent = replacetext(lowertext(string), " ", "") //95% of the time, the reagent id is a lowercase/no spaces version of the name + var/input_reagent = replacetext(LOWER_TEXT(string), " ", "") //95% of the time, the reagent id is a lowercase/no spaces version of the name if (isnull(input_reagent)) return @@ -194,7 +194,7 @@ /proc/get_chem_id(chem_name) for(var/X in GLOB.chemical_reagents_list) var/datum/reagent/R = GLOB.chemical_reagents_list[X] - if(ckey(chem_name) == ckey(lowertext(R.name))) + if(ckey(chem_name) == ckey(LOWER_TEXT(R.name))) return X ///Takes a type in and returns a list of associated recipes diff --git a/code/__HELPERS/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm index 002ac24c732..e57cf1b5098 100644 --- a/code/__HELPERS/sanitize_values.dm +++ b/code/__HELPERS/sanitize_values.dm @@ -78,7 +78,7 @@ if(97 to 102) //letters a to f . += char if(65 to 70) //letters A to F - char = lowertext(char) + char = LOWER_TEXT(char) . += char else break diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index e2fb0203a3e..4acfc1d6508 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -785,7 +785,7 @@ GLOBAL_LIST_INIT(binary, list("0","1")) return string var/base = next_backslash == 1 ? "" : copytext(string, 1, next_backslash) - var/macro = lowertext(copytext(string, next_backslash + length(string[next_backslash]), next_space)) + var/macro = LOWER_TEXT(copytext(string, next_backslash + length(string[next_backslash]), next_space)) var/rest = next_backslash > leng ? "" : copytext(string, next_space + length(string[next_space])) //See https://secure.byond.com/docs/ref/info.html#/DM/text/macros @@ -1082,7 +1082,7 @@ GLOBAL_LIST_INIT(binary, list("0","1")) var/text_length = length(text) //remove caps since words will be shuffled - text = lowertext(text) + text = LOWER_TEXT(text) //remove punctuation for same reasons as above var/punctuation = "" var/punctuation_hit_list = list("!","?",".","-") diff --git a/code/__HELPERS/turfs.dm b/code/__HELPERS/turfs.dm index 32a570ae8fc..c44845a5854 100644 --- a/code/__HELPERS/turfs.dm +++ b/code/__HELPERS/turfs.dm @@ -413,3 +413,20 @@ Turf and target are separate in case you want to teleport some distance from a t if(locate(type_to_find) in location) return TRUE return FALSE + +/** + * get_blueprint_data + * Gets a list of turfs around a central turf and gets the blueprint data in a list + * Args: + * - central_turf: The center turf we're getting data from. + * - viewsize: The viewsize we're getting the turfs around central_turf of. + */ +/proc/get_blueprint_data(turf/central_turf, viewsize) + var/list/blueprint_data_returned = list() + var/list/dimensions = getviewsize(viewsize) + var/horizontal_radius = dimensions[1] / 2 + var/vertical_radius = dimensions[2] / 2 + for(var/turf/nearby_turf as anything in RECT_TURFS(horizontal_radius, vertical_radius, central_turf)) + if(nearby_turf.blueprint_data) + blueprint_data_returned += nearby_turf.blueprint_data + return blueprint_data_returned diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 7e97724b562..7cdecfe41ed 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -389,7 +389,7 @@ GLOBAL_LIST_INIT(modulo_angle_to_dir, list(NORTH,NORTHEAST,EAST,SOUTHEAST,SOUTH, if(/turf) return "turf" else //regex everything else (works for /proc too) - return lowertext(replacetext("[the_type]", "[type2parent(the_type)]/", "")) + return LOWER_TEXT(replacetext("[the_type]", "[type2parent(the_type)]/", "")) /// Return html to load a url. /// for use inside of browse() calls to html assets that might be loaded on a cdn. diff --git a/code/_globalvars/arcade.dm b/code/_globalvars/arcade.dm new file mode 100644 index 00000000000..4143ce5fa76 --- /dev/null +++ b/code/_globalvars/arcade.dm @@ -0,0 +1,73 @@ +///List of all things that can be dispensed by an arcade cabinet and the weight of them being picked. +GLOBAL_LIST_INIT(arcade_prize_pool, list( + /obj/item/storage/box/snappops = 2, + /obj/item/toy/talking/ai = 2, + /obj/item/toy/talking/codex_gigas = 2, + /obj/item/clothing/under/syndicate/tacticool = 2, + /obj/item/toy/sword = 2, + /obj/item/toy/gun = 2, + /obj/item/gun/ballistic/shotgun/toy/crossbow = 2, + /obj/item/storage/box/fakesyndiesuit = 2, + /obj/item/storage/crayons = 2, + /obj/item/toy/spinningtoy = 2, + /obj/item/toy/spinningtoy/dark_matter = 1, + /obj/item/toy/balloon/arrest = 2, + /obj/item/toy/mecha/ripley = 1, + /obj/item/toy/mecha/ripleymkii = 1, + /obj/item/toy/mecha/hauler = 1, + /obj/item/toy/mecha/clarke = 1, + /obj/item/toy/mecha/odysseus = 1, + /obj/item/toy/mecha/gygax = 1, + /obj/item/toy/mecha/durand = 1, + /obj/item/toy/mecha/savannahivanov = 1, + /obj/item/toy/mecha/phazon = 1, + /obj/item/toy/mecha/honk = 1, + /obj/item/toy/mecha/darkgygax = 1, + /obj/item/toy/mecha/mauler = 1, + /obj/item/toy/mecha/darkhonk = 1, + /obj/item/toy/mecha/deathripley = 1, + /obj/item/toy/mecha/reticence = 1, + /obj/item/toy/mecha/marauder = 1, + /obj/item/toy/mecha/seraph = 1, + /obj/item/toy/mecha/firefighter = 1, + /obj/item/toy/cards/deck = 2, + /obj/item/toy/nuke = 2, + /obj/item/toy/minimeteor = 2, + /obj/item/toy/redbutton = 2, + /obj/item/toy/talking/owl = 2, + /obj/item/toy/talking/griffin = 2, + /obj/item/coin/antagtoken = 2, + /obj/item/stack/tile/fakepit/loaded = 2, + /obj/item/stack/tile/eighties/loaded = 2, + /obj/item/toy/toy_xeno = 2, + /obj/item/storage/box/actionfigure = 1, + /obj/item/restraints/handcuffs/fake = 2, + /obj/item/grenade/chem_grenade/glitter/pink = 1, + /obj/item/grenade/chem_grenade/glitter/blue = 1, + /obj/item/grenade/chem_grenade/glitter/white = 1, + /obj/item/toy/eightball = 2, + /obj/item/toy/windup_toolbox = 2, + /obj/item/toy/clockwork_watch = 2, + /obj/item/toy/toy_dagger = 2, + /obj/item/extendohand/acme = 1, + /obj/item/hot_potato/harmless/toy = 1, + /obj/item/card/emagfake = 1, + /obj/item/clothing/shoes/wheelys = 2, + /obj/item/clothing/shoes/kindle_kicks = 2, + /obj/item/toy/plush/goatplushie = 2, + /obj/item/toy/plush/moth = 2, + /obj/item/toy/plush/pkplush = 2, + /obj/item/toy/plush/rouny = 2, + /obj/item/toy/plush/abductor = 2, + /obj/item/toy/plush/abductor/agent = 2, + /obj/item/toy/plush/shark = 2, + /obj/item/storage/belt/military/snack/full = 2, + /obj/item/toy/brokenradio = 2, + /obj/item/toy/braintoy = 2, + /obj/item/toy/eldritch_book = 2, + /obj/item/storage/box/heretic_box = 1, + /obj/item/toy/foamfinger = 2, + /obj/item/clothing/glasses/trickblindfold = 2, + /obj/item/clothing/mask/party_horn = 2, + /obj/item/storage/box/party_poppers = 2, +)) diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 5a43e73cd6c..cce0793a5b1 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -153,15 +153,14 @@ DEFINE_BITFIELD(interaction_flags_atom, list( )) DEFINE_BITFIELD(interaction_flags_machine, list( - "INTERACT_MACHINE_ALLOW_SILICON" = INTERACT_MACHINE_ALLOW_SILICON, - "INTERACT_MACHINE_OFFLINE" = INTERACT_MACHINE_OFFLINE, "INTERACT_MACHINE_OPEN" = INTERACT_MACHINE_OPEN, + "INTERACT_MACHINE_OFFLINE" = INTERACT_MACHINE_OFFLINE, + "INTERACT_MACHINE_WIRES_IF_OPEN" = INTERACT_MACHINE_WIRES_IF_OPEN, + "INTERACT_MACHINE_ALLOW_SILICON" = INTERACT_MACHINE_ALLOW_SILICON, "INTERACT_MACHINE_OPEN_SILICON" = INTERACT_MACHINE_OPEN_SILICON, + "INTERACT_MACHINE_REQUIRES_SILICON" = INTERACT_MACHINE_REQUIRES_SILICON, "INTERACT_MACHINE_REQUIRES_SIGHT" = INTERACT_MACHINE_REQUIRES_SIGHT, "INTERACT_MACHINE_REQUIRES_LITERACY" = INTERACT_MACHINE_REQUIRES_LITERACY, - "INTERACT_MACHINE_REQUIRES_SILICON" = INTERACT_MACHINE_REQUIRES_SILICON, - "INTERACT_MACHINE_SET_MACHINE" = INTERACT_MACHINE_SET_MACHINE, - "INTERACT_MACHINE_WIRES_IF_OPEN" = INTERACT_MACHINE_WIRES_IF_OPEN, )) DEFINE_BITFIELD(interaction_flags_item, list( @@ -283,20 +282,20 @@ DEFINE_BITFIELD(movement_type, list( )) DEFINE_BITFIELD(obj_flags, list( - "BLOCK_Z_IN_DOWN" = BLOCK_Z_IN_DOWN, - "BLOCK_Z_IN_UP" = BLOCK_Z_IN_UP, + "EMAGGED" = EMAGGED, + "CAN_BE_HIT" = CAN_BE_HIT, + "DANGEROUS_POSSESSION" = DANGEROUS_POSSESSION, + "UNIQUE_RENAME" = UNIQUE_RENAME, "BLOCK_Z_OUT_DOWN" = BLOCK_Z_OUT_DOWN, "BLOCK_Z_OUT_UP" = BLOCK_Z_OUT_UP, - "BLOCKS_CONSTRUCTION_DIR" = BLOCKS_CONSTRUCTION_DIR, + "BLOCK_Z_IN_DOWN" = BLOCK_Z_IN_DOWN, + "BLOCK_Z_IN_UP" = BLOCK_Z_IN_UP, "BLOCKS_CONSTRUCTION" = BLOCKS_CONSTRUCTION, - "CAN_BE_HIT" = CAN_BE_HIT, - "CONDUCTS_ELECTRICITY" = CONDUCTS_ELECTRICITY, - "DANGEROUS_POSSESSION" = DANGEROUS_POSSESSION, - "EMAGGED" = EMAGGED, + "BLOCKS_CONSTRUCTION_DIR" = BLOCKS_CONSTRUCTION_DIR, "IGNORE_DENSITY" = IGNORE_DENSITY, - "IN_USE" = IN_USE, - "NO_DECONSTRUCTION" = NO_DECONSTRUCTION, - "UNIQUE_RENAME" = UNIQUE_RENAME, + "INFINITE_RESKIN" = INFINITE_RESKIN, + "CONDUCTS_ELECTRICITY" = CONDUCTS_ELECTRICITY, + "NO_DEBRIS_AFTER_DECONSTRUCTION" = NO_DEBRIS_AFTER_DECONSTRUCTION, )) DEFINE_BITFIELD(pass_flags, list( diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 1956a6061ad..749dfd49b21 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -127,6 +127,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_ALWAYS_WANTED" = TRAIT_ALWAYS_WANTED, "TRAIT_ANALGESIA" = TRAIT_ANALGESIA, "TRAIT_ANGELIC" = TRAIT_ANGELIC, + "TRAIT_ANOSMIA" = TRAIT_ANOSMIA, "TRAIT_ANTENNAE" = TRAIT_ANTENNAE, "TRAIT_ANTICONVULSANT" = TRAIT_ANTICONVULSANT, "TRAIT_ANTIMAGIC" = TRAIT_ANTIMAGIC, @@ -135,6 +136,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_BADDNA" = TRAIT_BADDNA, "TRAIT_BADTOUCH" = TRAIT_BADTOUCH, "TRAIT_BALD" = TRAIT_BALD, + "TRAIT_BALLOON_SUTRA" = TRAIT_BALLOON_SUTRA, "TRAIT_BATON_RESISTANCE" = TRAIT_BATON_RESISTANCE, "TRAIT_BEING_BLADE_SHIELDED" = TRAIT_BEING_BLADE_SHIELDED, "TRAIT_BLOB_ALLY" = TRAIT_BLOB_ALLY, @@ -361,6 +363,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_OVERWATCHED" = TRAIT_OVERWATCHED, "TRAIT_OVERWATCH_IMMUNE" = TRAIT_OVERWATCH_IMMUNE, "TRAIT_PACIFISM" = TRAIT_PACIFISM, + "TRAIT_PAPER_MASTER" = TRAIT_PAPER_MASTER, "TRAIT_PARALYSIS_L_ARM" = TRAIT_PARALYSIS_L_ARM, "TRAIT_PARALYSIS_L_LEG" = TRAIT_PARALYSIS_L_LEG, "TRAIT_PARALYSIS_R_ARM" = TRAIT_PARALYSIS_R_ARM, @@ -417,7 +420,6 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_SHIFTY_EYES" = TRAIT_SHIFTY_EYES, "TRAIT_SHOCKIMMUNE" = TRAIT_SHOCKIMMUNE, "TRAIT_SIGN_LANG" = TRAIT_SIGN_LANG, - "TRAIT_PAPER_MASTER" = TRAIT_PAPER_MASTER, "TRAIT_SILENT_FOOTSTEPS" = TRAIT_SILENT_FOOTSTEPS, "TRAIT_SIXTHSENSE" = TRAIT_SIXTHSENSE, "TRAIT_SKITTISH" = TRAIT_SKITTISH, @@ -439,6 +441,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_STASIS" = TRAIT_STASIS, "TRAIT_STIMULATED" = TRAIT_STIMULATED, "TRAIT_STRONG_GRABBER" = TRAIT_STRONG_GRABBER, + "TRAIT_STRONG_STOMACH" = TRAIT_STRONG_STOMACH, "TRAIT_STUNIMMUNE" = TRAIT_STUNIMMUNE, "TRAIT_SUCCUMB_OVERRIDE" = TRAIT_SUCCUMB_OVERRIDE, "TRAIT_SUICIDED" = TRAIT_SUICIDED, @@ -601,6 +604,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( ), /turf = list( "TRAIT_CHASM_STOPPED" = TRAIT_CHASM_STOPPED, + "TRAIT_CONTAINMENT_FIELD" = TRAIT_CONTAINMENT_FIELD, "TRAIT_FIREDOOR_STOP" = TRAIT_FIREDOOR_STOP, "TRAIT_HYPERSPACE_STOPPED" = TRAIT_HYPERSPACE_STOPPED, "TRAIT_IMMERSE_STOPPED" = TRAIT_IMMERSE_STOPPED, diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm index d30917b197e..5fe6883e82b 100644 --- a/code/_globalvars/traits/admin_tooling.dm +++ b/code/_globalvars/traits/admin_tooling.dm @@ -29,6 +29,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_AGENDER" = TRAIT_AGENDER, "TRAIT_AGEUSIA" = TRAIT_AGEUSIA, "TRAIT_ALCOHOL_TOLERANCE" = TRAIT_ALCOHOL_TOLERANCE, + "TRAIT_ANOSMIA" = TRAIT_ANOSMIA, "TRAIT_ANTIMAGIC" = TRAIT_ANTIMAGIC, "TRAIT_ANXIOUS" = TRAIT_ANXIOUS, "TRAIT_BADDNA" = TRAIT_BADDNA, @@ -159,6 +160,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_OIL_FRIED" = TRAIT_OIL_FRIED, "TRAIT_OVERWATCH_IMMUNE" = TRAIT_OVERWATCH_IMMUNE, "TRAIT_PACIFISM" = TRAIT_PACIFISM, + "TRAIT_PAPER_MASTER" = TRAIT_PAPER_MASTER, "TRAIT_PARALYSIS_L_ARM" = TRAIT_PARALYSIS_L_ARM, "TRAIT_PARALYSIS_L_LEG" = TRAIT_PARALYSIS_L_LEG, "TRAIT_PARALYSIS_R_ARM" = TRAIT_PARALYSIS_R_ARM, @@ -191,7 +193,6 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_SHIFTY_EYES" = TRAIT_SHIFTY_EYES, "TRAIT_SHOCKIMMUNE" = TRAIT_SHOCKIMMUNE, "TRAIT_SIGN_LANG" = TRAIT_SIGN_LANG, - "TRAIT_PAPER_MASTER" = TRAIT_PAPER_MASTER, "TRAIT_SILENT_FOOTSTEPS" = TRAIT_SILENT_FOOTSTEPS, "TRAIT_SIXTHSENSE" = TRAIT_SIXTHSENSE, "TRAIT_SKITTISH" = TRAIT_SKITTISH, @@ -205,6 +206,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_STABLEHEART" = TRAIT_STABLEHEART, "TRAIT_STABLELIVER" = TRAIT_STABLELIVER, "TRAIT_STRONG_GRABBER" = TRAIT_STRONG_GRABBER, + "TRAIT_STRONG_STOMACH" = TRAIT_STRONG_STOMACH, "TRAIT_STUNIMMUNE" = TRAIT_STUNIMMUNE, "TRAIT_SURGEON" = TRAIT_SURGEON, "TRAIT_SURGICALLY_ANALYZED" = TRAIT_SURGICALLY_ANALYZED, diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index c8c35b30847..0a6e54a46e0 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -55,7 +55,7 @@ ShiftClickOn(A) return if(LAZYACCESS(modifiers, ALT_CLICK)) // alt and alt-gr (rightalt) - AltClickOn(A) + A.ai_click_alt(src) return if(LAZYACCESS(modifiers, CTRL_CLICK)) CtrlClickOn(A) @@ -120,8 +120,6 @@ /mob/living/silicon/ai/CtrlClickOn(atom/target) target.AICtrlClick(src) -/mob/living/silicon/ai/AltClickOn(atom/target) - target.AIAltClick(src) /* The following criminally helpful code is just the previous code cleaned up; @@ -133,8 +131,7 @@ /atom/proc/AICtrlClick(mob/living/silicon/ai/user) return -/atom/proc/AIAltClick(mob/living/silicon/ai/user) - AltClick(user) +/atom/proc/ai_click_alt(mob/living/silicon/ai/user) return /atom/proc/AIShiftClick(mob/living/silicon/ai/user) @@ -150,7 +147,7 @@ toggle_bolt(user) add_hiddenprint(user) -/obj/machinery/door/airlock/AIAltClick(mob/living/silicon/ai/user) // Eletrifies doors. +/obj/machinery/door/airlock/ai_click_alt(mob/living/silicon/ai/user) if(obj_flags & EMAGGED) return @@ -219,7 +216,7 @@ update() /// Toggle APC equipment settings -/obj/machinery/power/apc/AIAltClick(mob/living/silicon/ai/user) +/obj/machinery/power/apc/ai_click_alt(mob/living/silicon/ai/user) if(!can_use(user, loud = TRUE)) return @@ -243,7 +240,7 @@ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN /* AI Turrets */ -/obj/machinery/turretid/AIAltClick(mob/living/silicon/ai/user) //toggles lethal on turrets +/obj/machinery/turretid/ai_click_alt(mob/living/silicon/ai/user) //toggles lethal on turrets if(ailock) return toggle_lethal(user) @@ -254,7 +251,7 @@ toggle_on(user) /* Holopads */ -/obj/machinery/holopad/AIAltClick(mob/living/silicon/ai/user) +/obj/machinery/holopad/ai_click_alt(mob/living/silicon/ai/user) if (user) balloon_alert(user, "disrupted all active calls") add_hiddenprint(user) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 566256824bf..af391efc859 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -96,7 +96,7 @@ if(LAZYACCESS(modifiers, RIGHT_CLICK)) alt_click_on_secondary(A) else - AltClickOn(A) + base_click_alt(A) return if(LAZYACCESS(modifiers, CTRL_CLICK)) CtrlClickOn(A) @@ -385,24 +385,6 @@ A.CtrlClick(src) return -/** - * Alt click - * Unused except for AI - */ -/mob/proc/AltClickOn(atom/A) - . = SEND_SIGNAL(src, COMSIG_MOB_ALTCLICKON, A) - if(. & COMSIG_MOB_CANCEL_CLICKON) - return - A.AltClick(src) - -/atom/proc/AltClick(mob/user) - if(!user.can_interact_with(src)) - return FALSE - if(SEND_SIGNAL(src, COMSIG_CLICK_ALT, user) & COMPONENT_CANCEL_CLICK_ALT) - return - var/turf/T = get_turf(src) - if(T && (isturf(loc) || isturf(src)) && user.TurfAdjacent(T) && !HAS_TRAIT(user, TRAIT_MOVE_VENTCRAWLING)) - user.set_listed_turf(T) ///The base proc of when something is right clicked on when alt is held - generally use alt_click_secondary instead /atom/proc/alt_click_on_secondary(atom/A) @@ -421,14 +403,8 @@ user.client.toggle_tag_datum(src) return -/// Use this instead of [/mob/proc/AltClickOn] where you only want turf content listing without additional atom alt-click interaction -/atom/proc/AltClickNoInteract(mob/user, atom/A) - var/turf/T = get_turf(A) - if(T && user.TurfAdjacent(T)) - user.set_listed_turf(T) - -/mob/proc/TurfAdjacent(turf/T) - return T.Adjacent(src) +/mob/proc/TurfAdjacent(turf/tile) + return tile.Adjacent(src) /** * Control+Shift click diff --git a/code/_onclick/click_alt.dm b/code/_onclick/click_alt.dm new file mode 100644 index 00000000000..16c8e843995 --- /dev/null +++ b/code/_onclick/click_alt.dm @@ -0,0 +1,66 @@ +/** + * ### Base proc for alt click interaction. + * + * If you wish to add custom `click_alt` behavior for a single type, use that proc. + */ +/mob/proc/base_click_alt(atom/target) + SHOULD_NOT_OVERRIDE(TRUE) + + var/turf/tile = isturf(target) ? target : get_turf(target) + + if(isobserver(src) || isrevenant(src)) + open_lootpanel(tile) + return + + if(!isturf(target) && can_perform_action(target, (target.interaction_flags_click | SILENT_ADJACENCY))) + if(SEND_SIGNAL(target, COMSIG_CLICK_ALT, src) & CLICK_ACTION_ANY) + return + + if(target.click_alt(src) & CLICK_ACTION_ANY) + return + + open_lootpanel(tile) + + +/// Helper for opening the lootpanel +/mob/proc/open_lootpanel(turf/target) + if(HAS_TRAIT(src, TRAIT_MOVE_VENTCRAWLING)) + return + + var/datum/lootpanel/panel = client?.loot_panel + if(isnull(panel)) + return + + panel.open(target) + + +/** + * ## Custom alt click interaction + * Override this to change default alt click behavior. Return `CLICK_ACTION_SUCCESS`, `CLICK_ACTION_BLOCKING` or `NONE`. + * + * ### Guard clauses + * Consider adding `interaction_flags_click` before adding unique guard clauses. + * + * ### Return flags + * Forgetting your return will cause the default alt click behavior to occur thereafter. + * + * The difference between NONE and BLOCKING can get hazy, but I like to keep NONE limited to guard clauses and "never" cases. + * + * A good usage for BLOCKING over NONE is when it's situational for the item and there's some feedback indicating this. + * + * ### Examples: + * User is a ghost, alt clicks on item with special disk eject: NONE + * + * Machine broken, no feedback: NONE + * + * Alt click a pipe to max output but its already max: BLOCKING + * + * Alt click a gun that normally works, but is out of ammo: BLOCKING + * + * User unauthorized, machine beeps: BLOCKING + * + * @param {mob} user - The person doing the alt clicking. + */ +/atom/proc/click_alt(mob/user) + SHOULD_CALL_PARENT(FALSE) + return NONE diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm index 8cad6f772e0..4f06e15f2cd 100644 --- a/code/_onclick/cyborg.dm +++ b/code/_onclick/cyborg.dm @@ -31,7 +31,7 @@ MiddleClickOn(A, params) return if(LAZYACCESS(modifiers, ALT_CLICK)) // alt and alt-gr (rightalt) - AltClickOn(A) + A.borg_click_alt(src) return if(LAZYACCESS(modifiers, CTRL_CLICK)) CtrlClickOn(A) @@ -89,7 +89,7 @@ if(after_attack_secondary_result == SECONDARY_ATTACK_CALL_NORMAL) W.afterattack(A, src, FALSE, params) - else + else W.afterattack(A, src, FALSE, params) //Give cyborgs hotkey clicks without breaking existing uses of hotkey clicks @@ -103,8 +103,6 @@ /mob/living/silicon/robot/CtrlClickOn(atom/target) target.BorgCtrlClick(src) -/mob/living/silicon/robot/AltClickOn(atom/target) - target.BorgAltClick(src) /atom/proc/BorgCtrlShiftClick(mob/living/silicon/robot/user) //forward to human click if not overridden CtrlShiftClick(user) @@ -152,9 +150,9 @@ else ..() -/obj/machinery/power/apc/BorgAltClick(mob/living/silicon/robot/user) +/obj/machinery/power/apc/borg_click_alt(mob/living/silicon/robot/user) if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled)) - AIAltClick(user) + ai_click_alt(user) else ..() @@ -171,19 +169,19 @@ else ..() -/atom/proc/BorgAltClick(mob/living/silicon/robot/user) - AltClick(user) +/atom/proc/borg_click_alt(mob/living/silicon/robot/user) + user.base_click_alt(src) return -/obj/machinery/door/airlock/BorgAltClick(mob/living/silicon/robot/user) // Eletrifies doors. Forwards to AI code. +/obj/machinery/door/airlock/borg_click_alt(mob/living/silicon/robot/user) // Eletrifies doors. Forwards to AI code. if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled)) - AIAltClick(user) + ai_click_alt(user) else ..() -/obj/machinery/turretid/BorgAltClick(mob/living/silicon/robot/user) //turret lethal on/off. Forwards to AI code. +/obj/machinery/turretid/borg_click_alt(mob/living/silicon/robot/user) //turret lethal on/off. Forwards to AI code. if(get_dist(src, user) <= user.interaction_range && !(user.control_disabled)) - AIAltClick(user) + ai_click_alt(user) else ..() diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm index b1f40f76294..e0a6c6873bd 100644 --- a/code/_onclick/hud/movable_screen_objects.dm +++ b/code/_onclick/hud/movable_screen_objects.dm @@ -44,40 +44,30 @@ offset[2] += y_off return offset_to_screen_loc(offset[1], offset[2], our_client?.view) -//Debug procs -/client/proc/test_movable_UI() - set category = "Debug" - set name = "Spawn Movable UI Object" - - var/atom/movable/screen/movable/M = new() +ADMIN_VERB(test_movable_UI, R_DEBUG, "Spawn Movable UI Object", "Spawn a movable UI object for testing.", ADMIN_CATEGORY_DEBUG) + var/atom/movable/screen/movable/M = new M.name = "Movable UI Object" M.icon_state = "block" M.maptext = MAPTEXT("Movable") M.maptext_width = 64 - var/screen_l = input(usr,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Movable UI Object") as text|null + var/screen_l = input(user, "Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Movable UI Object") as text|null if(!screen_l) return M.screen_loc = screen_l + user.screen += M - screen += M - - -/client/proc/test_snap_UI() - set category = "Debug" - set name = "Spawn Snap UI Object" - - var/atom/movable/screen/movable/snap/S = new() +ADMIN_VERB(test_snap_ui, R_DEBUG, "Spawn Snap UI Object", "Spawn a snap UI object for testing.", ADMIN_CATEGORY_DEBUG) + var/atom/movable/screen/movable/snap/S = new S.name = "Snap UI Object" S.icon_state = "block" S.maptext = MAPTEXT("Snap") S.maptext_width = 64 - var/screen_l = input(usr,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Snap UI Object") as text|null + var/screen_l = input(user,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Snap UI Object") as text|null if(!screen_l) return S.screen_loc = screen_l - - screen += S + user.screen += S diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index a3f886e656f..a1ca5ebf85a 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -11,7 +11,7 @@ var/list/modifiers = params2list(params) var/is_right_clicking = LAZYACCESS(modifiers, RIGHT_CLICK) - var/item_interact_result = target.item_interaction(user, src, modifiers, is_right_clicking) + var/item_interact_result = target.base_item_interaction(user, src, modifiers) if(item_interact_result & ITEM_INTERACT_SUCCESS) return TRUE if(item_interact_result & ITEM_INTERACT_BLOCKING) @@ -52,10 +52,6 @@ if (attackby_result) return TRUE - if(QDELETED(src) || QDELETED(target)) - attack_qdeleted(target, user, TRUE, params) - return TRUE - if (is_right_clicking) var/after_attack_secondary_result = afterattack_secondary(target, user, TRUE, params) @@ -163,7 +159,7 @@ return FALSE return attacking_item.attack_atom(src, user, params) -/mob/living/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) +/mob/living/item_interaction(mob/living/user, obj/item/tool, list/modifiers) // Surgery and such happens very high up in the interaction chain, before parent call var/attempt_tending = item_tending(user, tool, modifiers) if(attempt_tending & ITEM_INTERACT_ANY_BLOCKER) @@ -472,11 +468,6 @@ return SECONDARY_ATTACK_CALL_NORMAL -/// Called if the target gets deleted by our attack -/obj/item/proc/attack_qdeleted(atom/target, mob/user, proximity_flag, click_parameters) - SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_QDELETED, target, user, proximity_flag, click_parameters) - SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK_QDELETED, target, user, proximity_flag, click_parameters) - /obj/item/proc/get_clamped_volume() if(w_class) if(force) diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index 38d99a75e6c..ae2ebd97632 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -31,7 +31,7 @@ MiddleClickOn(A, params) return if(LAZYACCESS(modifiers, ALT_CLICK)) - AltClickNoInteract(src, A) + base_click_alt(A) return if(LAZYACCESS(modifiers, CTRL_CLICK)) CtrlClickOn(A) diff --git a/code/_onclick/overmind.dm b/code/_onclick/overmind.dm index d6b8994f82f..900ad59bde2 100644 --- a/code/_onclick/overmind.dm +++ b/code/_onclick/overmind.dm @@ -10,7 +10,7 @@ ShiftClickOn(A) return if(LAZYACCESS(modifiers, ALT_CLICK)) - AltClickOn(A) + blob_click_alt(A) return if(LAZYACCESS(modifiers, CTRL_CLICK)) CtrlClickOn(A) @@ -30,7 +30,7 @@ if(T) create_shield(T) -/mob/camera/blob/AltClickOn(atom/A) //Remove a blob +/mob/camera/blob/proc/blob_click_alt(atom/A) //Remove a blob var/turf/T = get_turf(A) if(T) remove_blob(T) diff --git a/code/controllers/admin.dm b/code/controllers/admin.dm index 421712d5ad4..5056e3804ef 100644 --- a/code/controllers/admin.dm +++ b/code/controllers/admin.dm @@ -44,15 +44,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick) usr.client.debug_variables(target) message_admins("Admin [key_name_admin(usr)] is debugging the [target] [class].") - -// Debug verbs. -/client/proc/restart_controller(controller in list("Master", "Failsafe")) - set category = "Debug" - set name = "Restart Controller" - set desc = "Restart one of the various periodic loop controllers for the game (be careful!)" - - if(!holder) - return +ADMIN_VERB(restart_controller, R_DEBUG, "Restart Controller", "Restart one of the various periodic loop controllers for the game (be careful!)", ADMIN_CATEGORY_DEBUG, controller in list("Master", "Failsafe")) switch(controller) if("Master") Recreate_MC() @@ -61,16 +53,9 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick) new /datum/controller/failsafe() BLACKBOX_LOG_ADMIN_VERB("Restart Failsafe Controller") - message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.") - -/client/proc/debug_controller() - set category = "Debug" - set name = "Debug Controller" - set desc = "Debug the various periodic loop controllers for the game (be careful!)" - - if(!holder) - return + message_admins("Admin [key_name_admin(user)] has restarted the [controller] controller.") +ADMIN_VERB(debug_controller, R_DEBUG, "Debug Controller", "Debug the various periodic loop controllers for the game (be careful!)", ADMIN_CATEGORY_DEBUG) var/list/controllers = list() var/list/controller_choices = list() @@ -85,7 +70,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick) if (!istype(controller)) return - debug_variables(controller) + SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/debug_variables, controller) BLACKBOX_LOG_ADMIN_VERB("Debug Controller") - message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.") + message_admins("Admin [key_name_admin(user)] is debugging the [controller] controller.") diff --git a/code/controllers/configuration/config_entry.dm b/code/controllers/configuration/config_entry.dm index fb1cf4bf5a6..7f28c361267 100644 --- a/code/controllers/configuration/config_entry.dm +++ b/code/controllers/configuration/config_entry.dm @@ -25,7 +25,7 @@ /datum/config_entry/New() if(type == abstract_type) CRASH("Abstract config entry [type] instatiated!") - name = lowertext(type2top(type)) + name = LOWER_TEXT(type2top(type)) default_protection = protection set_default() @@ -100,7 +100,7 @@ return FALSE config_entry_value = auto_trim ? trim(str_val) : str_val if(lowercase) - config_entry_value = lowertext(config_entry_value) + config_entry_value = LOWER_TEXT(config_entry_value) return TRUE /datum/config_entry/number @@ -148,7 +148,7 @@ return FALSE str_val = trim(str_val) if (str_val != "") - config_entry_value += lowercase ? lowertext(str_val) : str_val + config_entry_value += lowercase ? LOWER_TEXT(str_val) : str_val return TRUE /datum/config_entry/number_list @@ -246,7 +246,7 @@ config_key = jointext(config_entry_words, splitter) if(lowercase_key) - config_key = lowertext(config_key) + config_key = LOWER_TEXT(config_key) is_ambiguous = (length(config_entry_words) > 2) diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index 10c6cc4284f..2e5dfb468bd 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -170,7 +170,7 @@ if(IsAdminAdvancedProcCall()) return - var/filename_to_test = world.system_type == MS_WINDOWS ? lowertext(filename) : filename + var/filename_to_test = world.system_type == MS_WINDOWS ? LOWER_TEXT(filename) : filename if(filename_to_test in stack) log_config_error("Warning: Config recursion detected ([english_list(stack)]), breaking!") return @@ -197,10 +197,10 @@ var/value = null if(pos) - entry = lowertext(copytext(L, 1, pos)) + entry = LOWER_TEXT(copytext(L, 1, pos)) value = copytext(L, pos + length(L[pos])) else - entry = lowertext(L) + entry = LOWER_TEXT(L) if(!entry) continue @@ -215,7 +215,7 @@ // Reset directive, used for setting a config value back to defaults. Useful for string list config types if (entry == "$reset") - var/datum/config_entry/resetee = _entries[lowertext(value)] + var/datum/config_entry/resetee = _entries[LOWER_TEXT(value)] if (!value || !resetee) log_config_error("Warning: invalid $reset directive: [value]") continue @@ -366,10 +366,10 @@ Example config: var/data = null if(pos) - command = lowertext(copytext(t, 1, pos)) + command = LOWER_TEXT(copytext(t, 1, pos)) data = copytext(t, pos + length(t[pos])) else - command = lowertext(t) + command = LOWER_TEXT(t) if(!command) continue @@ -473,7 +473,7 @@ Example config: var/list/formatted_banned_words = list() for (var/banned_word in banned_words) - formatted_banned_words[lowertext(banned_word)] = banned_words[banned_word] + formatted_banned_words[LOWER_TEXT(banned_word)] = banned_words[banned_word] return formatted_banned_words /datum/controller/configuration/proc/compile_filter_regex(list/banned_words) diff --git a/code/controllers/configuration/entries/resources.dm b/code/controllers/configuration/entries/resources.dm index c839ccc078d..1fb8a6237d4 100644 --- a/code/controllers/configuration/entries/resources.dm +++ b/code/controllers/configuration/entries/resources.dm @@ -6,7 +6,7 @@ /datum/config_entry/string/asset_transport /datum/config_entry/string/asset_transport/ValidateAndSet(str_val) - return (lowertext(str_val) in list("simple", "webroot")) && ..(lowertext(str_val)) + return (LOWER_TEXT(str_val) in list("simple", "webroot")) && ..(LOWER_TEXT(str_val)) /datum/config_entry/string/asset_cdn_webroot protection = CONFIG_ENTRY_LOCKED diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 9aa6d821abb..d7996890f98 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -76,6 +76,9 @@ GLOBAL_REAL(Master, /datum/controller/master) ///used by CHECK_TICK as well so that the procs subsystems call can obey that SS's tick limits var/static/current_ticklimit = TICK_LIMIT_RUNNING + /// Whether the Overview UI will update as fast as possible for viewers. + var/overview_fast_update = FALSE + /datum/controller/master/New() if(!config) config = new @@ -135,6 +138,78 @@ GLOBAL_REAL(Master, /datum/controller/master) ss.Shutdown() log_world("Shutdown complete") +ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "View the current states of the Subsystem Controllers.", ADMIN_CATEGORY_SERVER) + Master.ui_interact(user.mob) + +/datum/controller/master/ui_status(mob/user, datum/ui_state/state) + if(!user.client?.holder?.check_for_rights(R_SERVER|R_DEBUG)) + return UI_CLOSE + return UI_INTERACTIVE + +/datum/controller/master/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(isnull(ui)) + ui = new /datum/tgui(user, src, "ControllerOverview") + ui.open() + +/datum/controller/master/ui_data(mob/user) + var/list/data = list() + + var/list/subsystem_data = list() + for(var/datum/controller/subsystem/subsystem as anything in subsystems) + subsystem_data += list(list( + "name" = subsystem.name, + "ref" = REF(subsystem), + "init_order" = subsystem.init_order, + "last_fire" = subsystem.last_fire, + "next_fire" = subsystem.next_fire, + "can_fire" = subsystem.can_fire, + "doesnt_fire" = !!(subsystem.flags & SS_NO_FIRE), + "cost_ms" = subsystem.cost, + "tick_usage" = subsystem.tick_usage, + "tick_overrun" = subsystem.tick_overrun, + "initialized" = subsystem.initialized, + "initialization_failure_message" = subsystem.initialization_failure_message, + )) + data["subsystems"] = subsystem_data + data["world_time"] = world.time + data["map_cpu"] = world.map_cpu + data["fast_update"] = overview_fast_update + + return data + +/datum/controller/master/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + if(..()) + return TRUE + + switch(action) + if("toggle_fast_update") + overview_fast_update = !overview_fast_update + return TRUE + + if("view_variables") + var/datum/controller/subsystem/subsystem = locate(params["ref"]) in subsystems + if(isnull(subsystem)) + to_chat(ui.user, span_warning("Failed to locate subsystem.")) + return + SSadmin_verbs.dynamic_invoke_verb(ui.user, /datum/admin_verb/debug_variables, subsystem) + return TRUE + +/datum/controller/master/proc/check_and_perform_fast_update() + PRIVATE_PROC(TRUE) + set waitfor = FALSE + + + if(!overview_fast_update) + return + + var/static/already_updating = FALSE + if(already_updating) + return + already_updating = TRUE + SStgui.update_uis(src) + already_updating = FALSE + // Returns 1 if we created a new mc, 0 if we couldn't due to a recent restart, // -1 if we encountered a runtime trying to recreate it /proc/Recreate_MC() @@ -582,11 +657,9 @@ GLOBAL_REAL(Master, /datum/controller/master) if (processing * sleep_delta <= world.tick_lag) current_ticklimit -= (TICK_LIMIT_RUNNING * 0.25) //reserve the tail 1/4 of the next tick for the mc if we plan on running next tick + check_and_perform_fast_update() sleep(world.tick_lag * (processing * sleep_delta)) - - - // This is what decides if something should run. /datum/controller/master/proc/CheckQueue(list/subsystemstocheck) . = 0 //so the mc knows if we runtimed diff --git a/code/controllers/subsystem/admin_verbs.dm b/code/controllers/subsystem/admin_verbs.dm new file mode 100644 index 00000000000..9496b95d998 --- /dev/null +++ b/code/controllers/subsystem/admin_verbs.dm @@ -0,0 +1,150 @@ +GENERAL_PROTECT_DATUM(/datum/controller/subsystem/admin_verbs) + +SUBSYSTEM_DEF(admin_verbs) + name = "Admin Verbs" + flags = SS_NO_FIRE + init_order = INIT_ORDER_ADMIN_VERBS + /// A list of all admin verbs indexed by their type. + var/list/datum/admin_verb/admin_verbs_by_type = list() + /// A list of all admin verbs indexed by their visibility flag. + var/list/list/datum/admin_verb/admin_verbs_by_visibility_flag = list() + /// A map of all assosciated admins and their visibility flags. + var/list/admin_visibility_flags = list() + /// A list of all admins that are pending initialization of this SS. + var/list/admins_pending_subsytem_init = list() + +/datum/controller/subsystem/admin_verbs/Initialize() + setup_verb_list() + process_pending_admins() + return SS_INIT_SUCCESS + +/datum/controller/subsystem/admin_verbs/Recover() + admin_verbs_by_type = SSadmin_verbs.admin_verbs_by_type + +/datum/controller/subsystem/admin_verbs/stat_entry(msg) + return "[..()] | V: [length(admin_verbs_by_type)]" + +/datum/controller/subsystem/admin_verbs/proc/process_pending_admins() + var/list/pending_admins = admins_pending_subsytem_init + admins_pending_subsytem_init = null + for(var/admin_ckey in pending_admins) + assosciate_admin(GLOB.directory[admin_ckey]) + +/datum/controller/subsystem/admin_verbs/proc/setup_verb_list() + if(length(admin_verbs_by_type)) + CRASH("Attempting to setup admin verbs twice!") + for(var/datum/admin_verb/verb_type as anything in subtypesof(/datum/admin_verb)) + var/datum/admin_verb/verb_singleton = new verb_type + if(!verb_singleton.__avd_check_should_exist()) + qdel(verb_singleton, force = TRUE) + continue + + admin_verbs_by_type[verb_type] = verb_singleton + if(verb_singleton.visibility_flag) + if(!(verb_singleton.visibility_flag in admin_verbs_by_visibility_flag)) + admin_verbs_by_visibility_flag[verb_singleton.visibility_flag] = list() + admin_verbs_by_visibility_flag[verb_singleton.visibility_flag] |= list(verb_singleton) + +/datum/controller/subsystem/admin_verbs/proc/get_valid_verbs_for_admin(client/admin) + if(isnull(admin.holder)) + CRASH("Why are we checking a non-admin for their valid... ahem... admin verbs?") + + var/list/has_permission = list() + for(var/permission_flag in GLOB.bitflags) + if(admin.holder.check_for_rights(permission_flag)) + has_permission["[permission_flag]"] = TRUE + + var/list/valid_verbs = list() + for(var/datum/admin_verb/verb_type as anything in admin_verbs_by_type) + var/datum/admin_verb/verb_singleton = admin_verbs_by_type[verb_type] + if(!verify_visibility(admin, verb_singleton)) + continue + + var/verb_permissions = verb_singleton.permissions + if(verb_permissions == R_NONE) + valid_verbs |= list(verb_singleton) + else for(var/permission_flag in bitfield_to_list(verb_permissions)) + if(!has_permission["[permission_flag]"]) + continue + valid_verbs |= list(verb_singleton) + + return valid_verbs + +/datum/controller/subsystem/admin_verbs/proc/verify_visibility(client/admin, datum/admin_verb/verb_singleton) + var/needed_flag = verb_singleton.visibility_flag + return !needed_flag || (needed_flag in admin_visibility_flags[admin.ckey]) + +/datum/controller/subsystem/admin_verbs/proc/update_visibility_flag(client/admin, flag, state) + if(state) + admin_visibility_flags[admin.ckey] |= list(flag) + assosciate_admin(admin) + return + + admin_visibility_flags[admin.ckey] -= list(flag) + // they lost the flag, iterate over verbs with that flag and yoink em + for(var/datum/admin_verb/verb_singleton as anything in admin_verbs_by_visibility_flag[flag]) + verb_singleton.unassign_from_client(admin) + admin.init_verbs() + +/datum/controller/subsystem/admin_verbs/proc/dynamic_invoke_verb(client/admin, datum/admin_verb/verb_type, ...) + if(IsAdminAdvancedProcCall()) + message_admins("PERMISSION ELEVATION: [key_name_admin(admin)] attempted to dynamically invoke admin verb '[verb_type]'.") + return + + if(ismob(admin)) + var/mob/mob = admin + admin = mob.client + + if(!ispath(verb_type, /datum/admin_verb) || verb_type == /datum/admin_verb) + CRASH("Attempted to dynamically invoke admin verb with invalid typepath '[verb_type]'.") + if(isnull(admin.holder)) + CRASH("Attempted to dynamically invoke admin verb '[verb_type]' with a non-admin.") + + var/list/verb_args = args.Copy() + verb_args.Cut(2, 3) + var/datum/admin_verb/verb_singleton = admin_verbs_by_type[verb_type] // this cannot be typed because we need to use `:` + if(isnull(verb_singleton)) + CRASH("Attempted to dynamically invoke admin verb '[verb_type]' that doesn't exist.") + + if(!admin.holder.check_for_rights(verb_singleton.permissions)) + to_chat(admin, span_adminnotice("You lack the permissions to do this.")) + return + + var/old_usr = usr + usr = admin.mob + // THE MACRO ENSURES THIS EXISTS. IF IT EVER DOESNT EXIST SOMEONE DIDNT USE THE DAMN MACRO! + verb_singleton.__avd_do_verb(arglist(verb_args)) + usr = old_usr + SSblackbox.record_feedback("tally", "dynamic_admin_verb_invocation", 1, "[verb_type]") + +/** + * Assosciates and/or resyncs an admin with their accessible admin verbs. + */ +/datum/controller/subsystem/admin_verbs/proc/assosciate_admin(client/admin) + if(IsAdminAdvancedProcCall()) + return + + if(!isnull(admins_pending_subsytem_init)) // if the list exists we are still initializing + to_chat(admin, span_big(span_green("Admin Verbs are still initializing. Please wait and you will be automatically assigned your verbs when it is complete."))) + admins_pending_subsytem_init |= list(admin.ckey) + return + + // refresh their verbs + admin_visibility_flags[admin.ckey] ||= list() + for(var/datum/admin_verb/verb_singleton as anything in get_valid_verbs_for_admin(admin)) + verb_singleton.assign_to_client(admin) + admin.init_verbs() + +/** + * Unassosciates an admin from their admin verbs. + * Goes over all admin verbs because we don't know which ones are assigned to the admin's mob without a bunch of extra bookkeeping. + * This might be a performance issue in the future if we have a lot of admin verbs. + */ +/datum/controller/subsystem/admin_verbs/proc/deassosciate_admin(client/admin) + if(IsAdminAdvancedProcCall()) + return + + UnregisterSignal(admin, COMSIG_CLIENT_MOB_LOGIN) + for(var/datum/admin_verb/verb_type as anything in admin_verbs_by_type) + admin_verbs_by_type[verb_type].unassign_from_client(admin) + admin_visibility_flags -= list(admin.ckey) diff --git a/code/controllers/subsystem/explosions.dm b/code/controllers/subsystem/explosions.dm index 1922d4a05f5..31de67361bf 100644 --- a/code/controllers/subsystem/explosions.dm +++ b/code/controllers/subsystem/explosions.dm @@ -87,12 +87,9 @@ SUBSYSTEM_DEF(explosions) throwturf -= T held_throwturf -= T -/client/proc/check_bomb_impacts() - set name = "Check Bomb Impact" - set category = "Debug" - - var/newmode = tgui_alert(usr, "Use reactionary explosions?","Check Bomb Impact", list("Yes", "No")) - var/turf/epicenter = get_turf(mob) +ADMIN_VERB(check_bomb_impacts, R_DEBUG, "Check Bomb Impact", "See what the effect of a bomb would be.", ADMIN_CATEGORY_DEBUG) + var/newmode = tgui_alert(user, "Use reactionary explosions?","Check Bomb Impact", list("Yes", "No")) + var/turf/epicenter = get_turf(user.mob) if(!epicenter) return @@ -100,7 +97,7 @@ SUBSYSTEM_DEF(explosions) var/heavy = 0 var/light = 0 var/list/choices = list("Small Bomb","Medium Bomb","Big Bomb","Custom Bomb") - var/choice = tgui_input_list(usr, "Pick the bomb size", "Bomb Size?", choices) + var/choice = tgui_input_list(user, "Pick the bomb size", "Bomb Size?", choices) switch(choice) if(null) return 0 @@ -117,9 +114,9 @@ SUBSYSTEM_DEF(explosions) heavy = 5 light = 7 if("Custom Bomb") - dev = input("Devastation range (Tiles):") as num - heavy = input("Heavy impact range (Tiles):") as num - light = input("Light impact range (Tiles):") as num + dev = input(user, "Devastation range (Tiles):") as num + heavy = input(user, "Heavy impact range (Tiles):") as num + light = input(user, "Light impact range (Tiles):") as num var/max_range = max(dev, heavy, light) var/x0 = epicenter.x @@ -208,9 +205,12 @@ SUBSYSTEM_DEF(explosions) * - flame_range: The range at which the explosion should produce hotspots. * - silent: Whether to generate/execute sound effects. * - smoke: Whether to generate a smoke cloud provided the explosion is powerful enough to warrant it. + * - protect_epicenter: Whether to leave the epicenter turf unaffected by the explosion * - explosion_cause: [Optional] The atom that caused the explosion, when different to the origin. Used for logging. + * - explosion_direction: The angle in which the explosion is pointed (for directional explosions.) + * - explosion_arc: The angle of the arc covered by a directional explosion (if 360 the explosion is non-directional.) */ -/proc/explosion(atom/origin, devastation_range = 0, heavy_impact_range = 0, light_impact_range = 0, flame_range = null, flash_range = null, adminlog = TRUE, ignorecap = FALSE, silent = FALSE, smoke = FALSE, atom/explosion_cause = null) +/proc/explosion(atom/origin, devastation_range = 0, heavy_impact_range = 0, light_impact_range = 0, flame_range = null, flash_range = null, adminlog = TRUE, ignorecap = FALSE, silent = FALSE, smoke = FALSE, protect_epicenter = FALSE, atom/explosion_cause = null, explosion_direction = 0, explosion_arc = 360) . = SSexplosions.explode(arglist(args)) @@ -228,9 +228,12 @@ SUBSYSTEM_DEF(explosions) * - flame_range: The range at which the explosion should produce hotspots. * - silent: Whether to generate/execute sound effects. * - smoke: Whether to generate a smoke cloud provided the explosion is powerful enough to warrant it. + * - protect_epicenter: Whether to leave the epicenter turf unaffected by the explosion * - explosion_cause: [Optional] The atom that caused the explosion, when different to the origin. Used for logging. + * - explosion_direction: The angle in which the explosion is pointed (for directional explosions.) + * - explosion_arc: The angle of the arc covered by a directional explosion (if 360 the explosion is non-directional.) */ -/datum/controller/subsystem/explosions/proc/explode(atom/origin, devastation_range = 0, heavy_impact_range = 0, light_impact_range = 0, flame_range = null, flash_range = null, adminlog = TRUE, ignorecap = FALSE, silent = FALSE, smoke = FALSE, atom/explosion_cause = null) +/datum/controller/subsystem/explosions/proc/explode(atom/origin, devastation_range = 0, heavy_impact_range = 0, light_impact_range = 0, flame_range = null, flash_range = null, adminlog = TRUE, ignorecap = FALSE, silent = FALSE, smoke = FALSE, protect_epicenter = FALSE, atom/explosion_cause = null, explosion_direction = 0, explosion_arc = 360) var/list/arguments = list( EXARG_KEY_ORIGIN = origin, EXARG_KEY_DEV_RANGE = devastation_range, @@ -242,7 +245,10 @@ SUBSYSTEM_DEF(explosions) EXARG_KEY_IGNORE_CAP = ignorecap, EXARG_KEY_SILENT = silent, EXARG_KEY_SMOKE = smoke, + EXARG_KEY_PROTECT_EPICENTER = protect_epicenter, EXARG_KEY_EXPLOSION_CAUSE = explosion_cause ? explosion_cause : origin, + EXARG_KEY_EXPLOSION_DIRECTION = explosion_direction, + EXARG_KEY_EXPLOSION_ARC = explosion_arc, ) var/atom/location = isturf(origin) ? origin : origin.loc if(SEND_SIGNAL(origin, COMSIG_ATOM_EXPLODE, arguments) & COMSIG_CANCEL_EXPLOSION) @@ -270,7 +276,7 @@ SUBSYSTEM_DEF(explosions) /** * Handles the effects of an explosion originating from a given point. * - * Primarily handles popagating the balstwave of the explosion to the relevant turfs. + * Primarily handles popagating the blastwave of the explosion to the relevant turfs. * Also handles the fireball from the explosion. * Also handles the smoke cloud from the explosion. * Also handles sfx and screenshake. @@ -286,9 +292,12 @@ SUBSYSTEM_DEF(explosions) * - flame_range: The range at which the explosion should produce hotspots. * - silent: Whether to generate/execute sound effects. * - smoke: Whether to generate a smoke cloud provided the explosion is powerful enough to warrant it. - * - explosion_cause: The atom that caused the explosion. Used for logging. + * - protect_epicenter: Whether to leave the epicenter turf unaffected by the explosion + * - explosion_cause: [Optional] The atom that caused the explosion, when different to the origin. Used for logging. + * - explosion_direction: The angle in which the explosion is pointed (for directional explosions.) + * - explosion_arc: The angle of the arc covered by a directional explosion (if 360 the explosion is non-directional.) */ -/datum/controller/subsystem/explosions/proc/propagate_blastwave(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flame_range, flash_range, adminlog, ignorecap, silent, smoke, atom/explosion_cause) +/datum/controller/subsystem/explosions/proc/propagate_blastwave(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flame_range, flash_range, adminlog, ignorecap, silent, smoke, protect_epicenter, atom/explosion_cause, explosion_direction, explosion_arc) epicenter = get_turf(epicenter) if(!epicenter) return @@ -387,7 +396,7 @@ SUBSYSTEM_DEF(explosions) for(var/mob/living/L in viewers(flash_range, epicenter)) L.flash_act() - var/list/affected_turfs = prepare_explosion_turfs(max_range, epicenter) + var/list/affected_turfs = prepare_explosion_turfs(max_range, epicenter, protect_epicenter, explosion_direction, explosion_arc) var/reactionary = CONFIG_GET(flag/reactionary_explosions) // this list is setup in the form position -> block for that position @@ -415,7 +424,6 @@ SUBSYSTEM_DEF(explosions) block += our_block cached_exp_block[explode] = our_block + explode.explosive_resistance - var/severity = EXPLODE_NONE if(dist + (block * EXPLOSION_BLOCK_DEV) < devastation_range) severity = EXPLODE_DEVASTATE @@ -585,10 +593,12 @@ SUBSYSTEM_DEF(explosions) /// Returns in a unique order, spiraling outwards /// This is done to ensure our progressive cache of blast resistance is always valid /// This is quite fast -/proc/prepare_explosion_turfs(range, turf/epicenter) +/proc/prepare_explosion_turfs(range, turf/epicenter, protect_epicenter, explosion_direction, explosion_arc) var/list/outlist = list() - // Add in the center - outlist += epicenter + var/list/candidates = list() + // Add in the center if it's not protected + if(!protect_epicenter) + outlist += epicenter var/our_x = epicenter.x var/our_y = epicenter.y @@ -596,6 +606,31 @@ SUBSYSTEM_DEF(explosions) var/max_x = world.maxx var/max_y = world.maxy + + // Work out the angles to explode between + var/first_angle_limit = WRAP(explosion_direction - explosion_arc * 0.5, 0, 360) + var/second_angle_limit = WRAP(explosion_direction + explosion_arc * 0.5, 0, 360) + + // Get everything in the right order + var/lower_angle_limit + var/upper_angle_limit + var/do_directional + var/reverse_angle + + // Work out which case we're in + if(first_angle_limit == second_angle_limit) // CASE A: FULL CIRCLE + do_directional = FALSE + else if(first_angle_limit < second_angle_limit) // CASE B: When the arc does not cross 0 degrees + lower_angle_limit = first_angle_limit + upper_angle_limit = second_angle_limit + do_directional = TRUE + reverse_angle = FALSE + else if (first_angle_limit > second_angle_limit) // CASE C: When the arc crosses 0 degrees + lower_angle_limit = second_angle_limit + upper_angle_limit = first_angle_limit + do_directional = TRUE + reverse_angle = TRUE + for(var/i in 1 to range) var/lowest_x = our_x - i var/lowest_y = our_y - i @@ -603,25 +638,32 @@ SUBSYSTEM_DEF(explosions) var/highest_y = our_y + i // top left to one before top right if(highest_y <= max_y) - outlist += block( + candidates += block( locate(max(lowest_x, 1), highest_y, our_z), locate(min(highest_x - 1, max_x), highest_y, our_z)) // top right to one before bottom right if(highest_x <= max_x) - outlist += block( + candidates += block( locate(highest_x, min(highest_y, max_y), our_z), locate(highest_x, max(lowest_y + 1, 1), our_z)) // bottom right to one before bottom left if(lowest_y >= 1) - outlist += block( + candidates += block( locate(min(highest_x, max_x), lowest_y, our_z), locate(max(lowest_x + 1, 1), lowest_y, our_z)) // bottom left to one before top left if(lowest_x >= 1) - outlist += block( + candidates += block( locate(lowest_x, max(lowest_y, 1), our_z), locate(lowest_x, min(highest_y - 1, max_y), our_z)) + if(!do_directional) + outlist += candidates + else + for(var/turf/candidate as anything in candidates) + var/angle = get_angle(epicenter, candidate) + if(ISINRANGE(angle, lower_angle_limit, upper_angle_limit) ^ reverse_angle) + outlist += candidate return outlist /datum/controller/subsystem/explosions/fire(resumed = 0) diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index b34f9551eb4..3aa9fba84e6 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -651,46 +651,38 @@ GLOBAL_LIST_EMPTY(the_station_areas) holodeck_templates[holo_template.template_id] = holo_template -//Manual loading of away missions. -/client/proc/admin_away() - set name = "Load Away Mission" - set category = "Admin.Events" - - if(!holder || !check_rights(R_FUN)) - return - - +ADMIN_VERB(load_away_mission, R_FUN, "Load Away Mission", "Load a specific away mission for the station.", ADMIN_CATEGORY_EVENTS) if(!GLOB.the_gateway) - if(tgui_alert(usr, "There's no home gateway on the station. You sure you want to continue ?", "Uh oh", list("Yes", "No")) != "Yes") + if(tgui_alert(user, "There's no home gateway on the station. You sure you want to continue ?", "Uh oh", list("Yes", "No")) != "Yes") return var/list/possible_options = GLOB.potentialRandomZlevels + "Custom" var/away_name var/datum/space_level/away_level var/secret = FALSE - if(tgui_alert(usr, "Do you want your mission secret? (This will prevent ghosts from looking at your map in any way other than through a living player's eyes.)", "Are you $$$ekret?", list("Yes", "No")) == "Yes") + if(tgui_alert(user, "Do you want your mission secret? (This will prevent ghosts from looking at your map in any way other than through a living player's eyes.)", "Are you $$$ekret?", list("Yes", "No")) == "Yes") secret = TRUE - var/answer = input("What kind?","Away") as null|anything in possible_options + var/answer = input(user, "What kind?","Away") as null|anything in possible_options switch(answer) if("Custom") - var/mapfile = input("Pick file:", "File") as null|file + var/mapfile = input(user, "Pick file:", "File") as null|file if(!mapfile) return away_name = "[mapfile] custom" - to_chat(usr,span_notice("Loading [away_name]...")) + to_chat(user,span_notice("Loading [away_name]...")) var/datum/map_template/template = new(mapfile, "Away Mission") away_level = template.load_new_z(secret) else if(answer in GLOB.potentialRandomZlevels) away_name = answer - to_chat(usr,span_notice("Loading [away_name]...")) + to_chat(user,span_notice("Loading [away_name]...")) var/datum/map_template/template = new(away_name, "Away Mission") away_level = template.load_new_z(secret) else return - message_admins("Admin [key_name_admin(usr)] has loaded [away_name] away mission.") - log_admin("Admin [key_name(usr)] has loaded [away_name] away mission.") + message_admins("Admin [key_name_admin(user)] has loaded [away_name] away mission.") + log_admin("Admin [key_name(user)] has loaded [away_name] away mission.") if(!away_level) message_admins("Loading [away_name] failed!") return diff --git a/code/controllers/subsystem/processing/obj_tab_items.dm b/code/controllers/subsystem/processing/obj_tab_items.dm deleted file mode 100644 index 53786daf011..00000000000 --- a/code/controllers/subsystem/processing/obj_tab_items.dm +++ /dev/null @@ -1,24 +0,0 @@ -PROCESSING_SUBSYSTEM_DEF(obj_tab_items) - name = "Obj Tab Items" - flags = SS_NO_INIT - runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT - wait = 0.1 SECONDS - -// I know this is mostly copypasta, but I want to change the processing logic -// Sorry bestie :( -/datum/controller/subsystem/processing/obj_tab_items/fire(resumed = FALSE) - if (!resumed) - currentrun = processing.Copy() - //cache for sanic speed (lists are references anyways) - var/list/current_run = currentrun - - while(current_run.len) - var/datum/thing = current_run[current_run.len] - if(QDELETED(thing)) - processing -= thing - else if(thing.process(wait * 0.1) == PROCESS_KILL) - // fully stop so that a future START_PROCESSING will work - STOP_PROCESSING(src, thing) - if (MC_TICK_CHECK) - return - current_run.len-- diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm index edeb63d3dc5..733b94d582a 100644 --- a/code/controllers/subsystem/statpanel.dm +++ b/code/controllers/subsystem/statpanel.dm @@ -112,12 +112,6 @@ SUBSYSTEM_DEF(statpanels) if(update_actions && num_fires % default_wait == 0) set_action_tabs(target, target_mob) - // Handle the examined turf of the stat panel, if it's been long enough, or if we've generated new images for it - var/turf/listed_turf = target_mob?.listed_turf - if(listed_turf && num_fires % default_wait == 0) - if(target.stat_tab == listed_turf.name || !(listed_turf.name in target.panel_tabs)) - set_turf_examine_tab(target, target_mob) - if(MC_TICK_CHECK) return @@ -190,71 +184,6 @@ SUBSYSTEM_DEF(statpanels) target.stat_panel.send_message("update_spells", list(spell_tabs = target.spell_tabs, actions = actions)) -/datum/controller/subsystem/statpanels/proc/set_turf_examine_tab(client/target, mob/target_mob) - var/list/overrides = list() - for(var/image/target_image as anything in target.images) - if(!target_image.loc || target_image.loc.loc != target_mob.listed_turf || !target_image.override) - continue - overrides += target_image.loc - - var/list/atoms_to_display = list(target_mob.listed_turf) - for(var/atom/movable/turf_content as anything in target_mob.listed_turf) - if(turf_content.mouse_opacity == MOUSE_OPACITY_TRANSPARENT) - continue - if(turf_content.invisibility > target_mob.see_invisible) - continue - if(turf_content in overrides) - continue - if(turf_content.IsObscured()) - continue - atoms_to_display += turf_content - - /// Set the atoms we're meant to display - var/datum/object_window_info/obj_window = target.obj_window - obj_window.atoms_to_show = atoms_to_display - START_PROCESSING(SSobj_tab_items, obj_window) - refresh_client_obj_view(target) - -/datum/controller/subsystem/statpanels/proc/refresh_client_obj_view(client/refresh) - var/list/turf_items = return_object_images(refresh) - if(!length(turf_items) || !refresh.mob?.listed_turf) - return - refresh.stat_panel.send_message("update_listedturf", turf_items) - -#define OBJ_IMAGE_LOADING "statpanels obj loading temporary" -/// Returns all our ready object tab images -/// Returns a list in the form list(list(object_name, object_ref, loaded_image), ...) -/datum/controller/subsystem/statpanels/proc/return_object_images(client/load_from) - // You might be inclined to think that this is a waste of cpu time, since we - // A: Double iterate over atoms in the build case, or - // B: Generate these lists over and over in the refresh case - // It's really not very hot. The hot portion of this code is genuinely mostly in the image generation - // So it's ok to pay a performance cost for cleanliness here - - // No turf? go away - if(!load_from.mob?.listed_turf) - return list() - var/datum/object_window_info/obj_window = load_from.obj_window - var/list/already_seen = obj_window.atoms_to_images - var/list/to_make = obj_window.atoms_to_imagify - var/list/turf_items = list() - for(var/atom/turf_item as anything in obj_window.atoms_to_show) - // First, we fill up the list of refs to display - // If we already have one, just use that - var/existing_image = already_seen[turf_item] - if(existing_image == OBJ_IMAGE_LOADING) - continue - // We already have it. Success! - if(existing_image) - turf_items[++turf_items.len] = list("[turf_item.name]", REF(turf_item), existing_image) - continue - // Now, we're gonna queue image generation out of those refs - to_make += turf_item - already_seen[turf_item] = OBJ_IMAGE_LOADING - obj_window.RegisterSignal(turf_item, COMSIG_QDELETING, TYPE_PROC_REF(/datum/object_window_info,viewing_atom_deleted)) // we reset cache if anything in it gets deleted - return turf_items - -#undef OBJ_IMAGE_LOADING /datum/controller/subsystem/statpanels/proc/generate_mc_data() mc_data = list( @@ -296,16 +225,6 @@ SUBSYSTEM_DEF(statpanels) set_action_tabs(target, target_mob) return TRUE - // Handle turfs - - if(target_mob?.listed_turf) - if(!target_mob.TurfAdjacent(target_mob.listed_turf)) - target_mob.set_listed_turf(null) - - else if(target.stat_tab == target_mob?.listed_turf.name || !(target_mob?.listed_turf.name in target.panel_tabs)) - set_turf_examine_tab(target, target_mob) - return TRUE - if(!target.holder) return FALSE @@ -325,105 +244,3 @@ SUBSYSTEM_DEF(statpanels) /// Stat panel window declaration /client/var/datum/tgui_window/stat_panel - -/// Datum that holds and tracks info about a client's object window -/// Really only exists because I want to be able to do logic with signals -/// And need a safe place to do the registration -/datum/object_window_info - /// list of atoms to show to our client via the object tab, at least currently - var/list/atoms_to_show = list() - /// list of atom -> image string for objects we have had in the right click tab - /// this is our caching - var/list/atoms_to_images = list() - /// list of atoms to turn into images for the object tab - var/list/atoms_to_imagify = list() - /// Our owner client - var/client/parent - /// Are we currently tracking a turf? - var/actively_tracking = FALSE - -/datum/object_window_info/New(client/parent) - . = ..() - src.parent = parent - -/datum/object_window_info/Destroy(force) - atoms_to_show = null - atoms_to_images = null - atoms_to_imagify = null - parent.obj_window = null - parent = null - STOP_PROCESSING(SSobj_tab_items, src) - return ..() - -/// Takes a client, attempts to generate object images for it -/// We will update the client with any improvements we make when we're done -/datum/object_window_info/process(seconds_per_tick) - // Cache the datum access for sonic speed - var/list/to_make = atoms_to_imagify - var/list/newly_seen = atoms_to_images - var/index = 0 - for(index in 1 to length(to_make)) - var/atom/thing = to_make[index] - - var/generated_string - if(ismob(thing) || length(thing.overlays) > 2) - generated_string = costly_icon2html(thing, parent, sourceonly=TRUE) - else - generated_string = icon2html(thing, parent, sourceonly=TRUE) - - newly_seen[thing] = generated_string - if(TICK_CHECK) - to_make.Cut(1, index + 1) - index = 0 - break - // If we've not cut yet, do it now - if(index) - to_make.Cut(1, index + 1) - SSstatpanels.refresh_client_obj_view(parent) - if(!length(to_make)) - return PROCESS_KILL - -/datum/object_window_info/proc/start_turf_tracking() - if(actively_tracking) - stop_turf_tracking() - var/static/list/connections = list( - COMSIG_MOVABLE_MOVED = PROC_REF(on_mob_move), - COMSIG_MOB_LOGOUT = PROC_REF(on_mob_logout), - ) - AddComponent(/datum/component/connect_mob_behalf, parent, connections) - actively_tracking = TRUE - -/datum/object_window_info/proc/stop_turf_tracking() - qdel(GetComponent(/datum/component/connect_mob_behalf)) - actively_tracking = FALSE - -/datum/object_window_info/proc/on_mob_move(mob/source) - SIGNAL_HANDLER - var/turf/listed = source.listed_turf - if(!listed || !source.TurfAdjacent(listed)) - source.set_listed_turf(null) - -/datum/object_window_info/proc/on_mob_logout(mob/source) - SIGNAL_HANDLER - on_mob_move(parent.mob) - -/// Clears any cached object window stuff -/// We use hard refs cause we'd need a signal for this anyway. Cleaner this way -/datum/object_window_info/proc/viewing_atom_deleted(atom/deleted) - SIGNAL_HANDLER - atoms_to_show -= deleted - atoms_to_imagify -= deleted - atoms_to_images -= deleted - -/mob/proc/set_listed_turf(turf/new_turf) - listed_turf = new_turf - if(!client) - return - if(!client.obj_window) - client.obj_window = new(client) - if(listed_turf) - client.stat_panel.send_message("create_listedturf", listed_turf.name) - client.obj_window.start_turf_tracking() - else - client.stat_panel.send_message("remove_listedturf") - client.obj_window.stop_turf_tracking() diff --git a/code/controllers/subsystem/tgui.dm b/code/controllers/subsystem/tgui.dm index c12c1b2bb32..cd03e1f3e52 100644 --- a/code/controllers/subsystem/tgui.dm +++ b/code/controllers/subsystem/tgui.dm @@ -122,8 +122,6 @@ SUBSYSTEM_DEF(tgui) for(var/datum/tgui/ui in user.tgui_open_uis) if(ui.window && ui.window.id == window_id) ui.close(can_be_suspended = FALSE) - // Unset machine just to be sure. - user.unset_machine() // Close window directly just to be sure. user << browse(null, "window=[window_id]") diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 4526a8b5a79..c15129d9345 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -92,7 +92,7 @@ SUBSYSTEM_DEF(ticker) var/use_rare_music = prob(1) for(var/S in provisional_title_music) - var/lower = lowertext(S) + var/lower = LOWER_TEXT(S) var/list/L = splittext(lower,"+") switch(L.len) if(3) //rare+MAP+sound.ogg or MAP+rare.sound.ogg -- Rare Map-specific sounds @@ -116,7 +116,7 @@ SUBSYSTEM_DEF(ticker) for(var/S in music) var/list/L = splittext(S,".") if(L.len >= 2) - var/ext = lowertext(L[L.len]) //pick the real extension, no 'honk.ogg.exe' nonsense here + var/ext = LOWER_TEXT(L[L.len]) //pick the real extension, no 'honk.ogg.exe' nonsense here if(byond_sound_formats[ext]) continue music -= S @@ -296,8 +296,8 @@ SUBSYSTEM_DEF(ticker) log_world("Game start took [(world.timeofday - init_start)/10]s") INVOKE_ASYNC(SSdbcore, TYPE_PROC_REF(/datum/controller/subsystem/dbcore,SetRoundStart)) - to_chat(world, span_notice("Welcome to [station_name()], enjoy your stay!")) - alert_sound_to_playing(sound(SSstation.announcer.get_rand_welcome_sound())) //SKYRAT EDIT CHANGE + to_chat(world, span_notice(span_bold("Welcome to [station_name()], enjoy your stay!"))) + SEND_SOUND(world, sound(SSstation.announcer.get_rand_welcome_sound())) current_state = GAME_STATE_PLAYING Master.SetRunLevel(RUNLEVEL_GAME) diff --git a/code/controllers/subsystem/title.dm b/code/controllers/subsystem/title.dm index 1fb7944191d..afddd1d01de 100644 --- a/code/controllers/subsystem/title.dm +++ b/code/controllers/subsystem/title.dm @@ -26,7 +26,7 @@ SUBSYSTEM_DEF(title) for(var/S in provisional_title_screens) var/list/L = splittext(S,"+") - if((L.len == 1 && (L[1] != "exclude" && L[1] != "blank.png")) || (L.len > 1 && ((use_rare_screens && lowertext(L[1]) == "rare") || (lowertext(L[1]) == lowertext(SSmapping.config.map_name))))) + if((L.len == 1 && (L[1] != "exclude" && L[1] != "blank.png")) || (L.len > 1 && ((use_rare_screens && LOWER_TEXT(L[1]) == "rare") || (LOWER_TEXT(L[1]) == LOWER_TEXT(SSmapping.config.map_name))))) title_screens += S if(length(title_screens)) diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm index 78c99f47903..b8496a623eb 100644 --- a/code/controllers/subsystem/weather.dm +++ b/code/controllers/subsystem/weather.dm @@ -86,15 +86,9 @@ SUBSYSTEM_DEF(weather) /datum/controller/subsystem/weather/proc/get_weather_by_type(type) return locate(type) in processing -/** - * Calls end() on all current weather effects that are currently processing in the weather subsystem. - */ -/client/proc/stop_weather() - set category = "Debug" - set name = "Stop All Active Weather" - - log_admin("[key_name(src)] stopped all currently active weather.") - message_admins("[key_name_admin(src)] stopped all currently active weather.") +ADMIN_VERB(stop_weather, R_DEBUG|R_ADMIN, "Stop All Active Weather", "Stop all currently active weather.", ADMIN_CATEGORY_DEBUG) + log_admin("[key_name(user)] stopped all currently active weather.") + message_admins("[key_name_admin(user)] stopped all currently active weather.") for(var/datum/weather/current_weather as anything in SSweather.processing) if(current_weather in SSweather.processing) current_weather.end() diff --git a/code/datums/ai/oldhostile/hostile_tameable.dm b/code/datums/ai/oldhostile/hostile_tameable.dm index 5c96eca17da..d76ffb8a282 100644 --- a/code/datums/ai/oldhostile/hostile_tameable.dm +++ b/code/datums/ai/oldhostile/hostile_tameable.dm @@ -108,7 +108,7 @@ return if(!istype(clicker) || blackboard[BB_HOSTILE_FRIEND] != clicker) return - . = COMPONENT_CANCEL_CLICK_ALT + . = CLICK_ACTION_BLOCKING INVOKE_ASYNC(src, PROC_REF(command_radial), clicker) /// Show the command radial menu diff --git a/code/datums/beam.dm b/code/datums/beam.dm index 52b649990d7..fe34b0c7edd 100644 --- a/code/datums/beam.dm +++ b/code/datums/beam.dm @@ -40,6 +40,8 @@ var/override_target_pixel_x = null /// If set will be used instead of targets's pixel_y in offset calculations var/override_target_pixel_y = null + ///the layer of our beam + var/beam_layer /datum/beam/New( origin, @@ -55,6 +57,7 @@ override_origin_pixel_y = null, override_target_pixel_x = null, override_target_pixel_y = null, + beam_layer = ABOVE_ALL_MOB_LAYER ) src.origin = origin src.target = target @@ -68,6 +71,7 @@ src.override_origin_pixel_y = override_origin_pixel_y src.override_target_pixel_x = override_target_pixel_x src.override_target_pixel_y = override_target_pixel_y + src.beam_layer = beam_layer if(time < INFINITY) QDEL_IN(src, time) @@ -81,6 +85,7 @@ visuals.color = beam_color visuals.vis_flags = VIS_INHERIT_PLANE|VIS_INHERIT_LAYER visuals.emissive = emissive + visuals.layer = beam_layer visuals.update_appearance() Draw() RegisterSignal(origin, COMSIG_MOVABLE_MOVED, PROC_REF(redrawing)) @@ -278,7 +283,18 @@ * maxdistance: how far the beam will go before stopping itself. Used mainly for two things: preventing lag if the beam may go in that direction and setting a range to abilities that use beams. * beam_type: The type of your custom beam. This is for adding other wacky stuff for your beam only. Most likely, you won't (and shouldn't) change it. */ -/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=INFINITY,maxdistance=INFINITY,beam_type=/obj/effect/ebeam, beam_color = null, emissive = TRUE, override_origin_pixel_x = null, override_origin_pixel_y = null, override_target_pixel_x = null, override_target_pixel_y = null) - var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type, beam_color, emissive, override_origin_pixel_x, override_origin_pixel_y, override_target_pixel_x, override_target_pixel_y ) +/atom/proc/Beam(atom/BeamTarget, + icon_state="b_beam", + icon='icons/effects/beam.dmi', + time=INFINITY,maxdistance=INFINITY, + beam_type=/obj/effect/ebeam, + beam_color = null, emissive = TRUE, + override_origin_pixel_x = null, + override_origin_pixel_y = null, + override_target_pixel_x = null, + override_target_pixel_y = null, + layer = ABOVE_ALL_MOB_LAYER +) + var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type, beam_color, emissive, override_origin_pixel_x, override_origin_pixel_y, override_target_pixel_x, override_target_pixel_y, layer) INVOKE_ASYNC(newbeam, TYPE_PROC_REF(/datum/beam/, Start)) return newbeam diff --git a/code/datums/brain_damage/hypnosis.dm b/code/datums/brain_damage/hypnosis.dm index dbaa571cacd..5630073c955 100644 --- a/code/datums/brain_damage/hypnosis.dm +++ b/code/datums/brain_damage/hypnosis.dm @@ -61,7 +61,7 @@ ..() if(SPT_PROB(1, seconds_per_tick)) if(prob(50)) - to_chat(owner, span_hypnophrase("...[lowertext(hypnotic_phrase)]...")) + to_chat(owner, span_hypnophrase("...[LOWER_TEXT(hypnotic_phrase)]...")) else owner.cause_hallucination( \ /datum/hallucination/chat, \ diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm index 18ca8172968..e3891392d1a 100644 --- a/code/datums/brain_damage/imaginary_friend.dm +++ b/code/datums/brain_damage/imaginary_friend.dm @@ -217,11 +217,11 @@ message = capitalize(message) if(message_mods[RADIO_EXTENSION] == MODE_ADMIN) - client?.cmd_admin_say(message) + SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/cmd_admin_say, message) return if(message_mods[RADIO_EXTENSION] == MODE_DEADMIN) - client?.dsay(message) + SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/dsay, message) return if(check_emote(message, forced)) diff --git a/code/datums/brain_damage/mild.dm b/code/datums/brain_damage/mild.dm index 21ecf1b520b..1d121d0db8a 100644 --- a/code/datums/brain_damage/mild.dm +++ b/code/datums/brain_damage/mild.dm @@ -212,7 +212,7 @@ word = copytext(word, 1, suffix_foundon) word = html_decode(word) - if(lowertext(word) in common_words) + if(LOWER_TEXT(word) in common_words) new_message += word + suffix else if(prob(30) && message_split.len > 2) diff --git a/code/datums/browser.dm b/code/datums/browser.dm index 08099b46f1a..f74ecf6c5a3 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -475,7 +475,3 @@ src.Topic(href, params2list(href), hsrc) // this will direct to the atom's return // Topic() proc via client.Topic() - // no atomref specified (or not found) - // so just reset the user mob's machine var - if(src?.mob) - src.mob.unset_machine() diff --git a/code/datums/cogbar.dm b/code/datums/cogbar.dm index c52092e5bd1..0b5ead1e51e 100644 --- a/code/datums/cogbar.dm +++ b/code/datums/cogbar.dm @@ -1,4 +1,4 @@ -#define COGBAR_ANIMATION_TIME 5 DECISECONDS +#define COGBAR_ANIMATION_TIME (0.5 SECONDS) /** * ### Cogbar diff --git a/code/datums/components/bakeable.dm b/code/datums/components/bakeable.dm index a745be2b1a5..afc71936f1b 100644 --- a/code/datums/components/bakeable.dm +++ b/code/datums/components/bakeable.dm @@ -90,11 +90,24 @@ baked_result.pixel_y = original_object.pixel_y used_tray.AddToPlate(baked_result) + var/list/asomnia_hadders = list() + for(var/mob/smeller in get_hearers_in_view(DEFAULT_MESSAGE_RANGE, used_oven)) + if(HAS_TRAIT(smeller, TRAIT_ANOSMIA)) + asomnia_hadders += smeller + if(positive_result) - used_oven.visible_message(span_notice("You smell something great coming from [used_oven]."), blind_message = span_notice("You smell something great...")) + used_oven.visible_message( + span_notice("You smell something great coming from [used_oven]."), + blind_message = span_notice("You smell something great..."), + ignored_mobs = asomnia_hadders, + ) BLACKBOX_LOG_FOOD_MADE(baked_result.type) else - used_oven.visible_message(span_warning("You smell a burnt smell coming from [used_oven]."), blind_message = span_warning("You smell a burnt smell...")) + used_oven.visible_message( + span_warning("You smell a burnt smell coming from [used_oven]."), + blind_message = span_warning("You smell a burnt smell..."), + ignored_mobs = asomnia_hadders, + ) SEND_SIGNAL(parent, COMSIG_ITEM_BAKED, baked_result) qdel(parent) diff --git a/code/datums/components/crafting/melee_weapon.dm b/code/datums/components/crafting/melee_weapon.dm index 23873a5d7af..869d223a758 100644 --- a/code/datums/components/crafting/melee_weapon.dm +++ b/code/datums/components/crafting/melee_weapon.dm @@ -44,6 +44,21 @@ time = 4 SECONDS category = CAT_WEAPON_MELEE + +/datum/crafting_recipe/balloon_mallet + name = "Balloon Mallet" + result = /obj/item/balloon_mallet + reqs = list( + /obj/item/toy/balloon/long = 18, + ) + time = 10 SECONDS + category = CAT_WEAPON_MELEE + +/datum/crafting_recipe/balloon_mallet/check_requirements(mob/user, list/collected_requirements) + . = ..() + if(HAS_TRAIT(user, TRAIT_BALLOON_SUTRA)) + return TRUE + /datum/crafting_recipe/tailwhip name = "Liz O' Nine Tails" result = /obj/item/melee/chainofcommand/tailwhip diff --git a/code/datums/components/crafting/tailoring.dm b/code/datums/components/crafting/tailoring.dm index 14a7ebfc21b..3476016ead3 100644 --- a/code/datums/components/crafting/tailoring.dm +++ b/code/datums/components/crafting/tailoring.dm @@ -442,3 +442,42 @@ /obj/item/clothing/suit/armor/vest = 1, ) category = CAT_CLOTHING + +/datum/crafting_recipe/balloon_helmet + result = /obj/item/clothing/head/helmet/balloon + reqs = list( + /obj/item/toy/balloon/long = 6, + ) + time = 4 SECONDS + category = CAT_CLOTHING + +/datum/crafting_recipe/balloon_helmet/check_requirements(mob/user, list/collected_requirements) + . = ..() + if(HAS_TRAIT(user, TRAIT_BALLOON_SUTRA)) + return TRUE + +/datum/crafting_recipe/balloon_tophat + result = /obj/item/clothing/head/hats/tophat/balloon + reqs = list( + /obj/item/toy/balloon/long = 6, + ) + time = 4 SECONDS + category = CAT_CLOTHING + +/datum/crafting_recipe/balloon_tophat/check_requirements(mob/user, list/collected_requirements) + . = ..() + if(HAS_TRAIT(user, TRAIT_BALLOON_SUTRA)) + return TRUE + +/datum/crafting_recipe/balloon_vest + result = /obj/item/clothing/suit/armor/balloon_vest + reqs = list( + /obj/item/toy/balloon/long = 18, + ) + time = 8 SECONDS + category = CAT_CLOTHING + +/datum/crafting_recipe/balloon_vest/check_requirements(mob/user, list/collected_requirements) + . = ..() + if(HAS_TRAIT(user, TRAIT_BALLOON_SUTRA)) + return TRUE diff --git a/code/datums/components/cult_ritual_item.dm b/code/datums/components/cult_ritual_item.dm index 74bac463e32..7d9710977ce 100644 --- a/code/datums/components/cult_ritual_item.dm +++ b/code/datums/components/cult_ritual_item.dm @@ -221,7 +221,7 @@ cultist.log_message("erased a [rune.cultist_name] rune with [parent].", LOG_GAME) message_admins("[ADMIN_LOOKUPFLW(cultist)] erased a [rune.cultist_name] rune with [parent].") - to_chat(cultist, span_notice("You carefully erase the [lowertext(rune.cultist_name)] rune.")) + to_chat(cultist, span_notice("You carefully erase the [LOWER_TEXT(rune.cultist_name)] rune.")) qdel(rune) /* @@ -338,8 +338,8 @@ var/obj/effect/rune/made_rune = new rune_to_scribe(our_turf, chosen_keyword) made_rune.add_mob_blood(cultist) - to_chat(cultist, span_cult("The [lowertext(made_rune.cultist_name)] rune [made_rune.cultist_desc]")) - cultist.log_message("scribed \a [lowertext(made_rune.cultist_name)] rune using [parent] ([parent.type])", LOG_GAME) + to_chat(cultist, span_cult("The [LOWER_TEXT(made_rune.cultist_name)] rune [made_rune.cultist_desc]")) + cultist.log_message("scribed \a [LOWER_TEXT(made_rune.cultist_name)] rune using [parent] ([parent.type])", LOG_GAME) SSblackbox.record_feedback("tally", "cult_runes_scribed", 1, made_rune.cultist_name) return TRUE diff --git a/code/datums/components/customizable_reagent_holder.dm b/code/datums/components/customizable_reagent_holder.dm index bd88508bec0..fd1b8a2ac64 100644 --- a/code/datums/components/customizable_reagent_holder.dm +++ b/code/datums/components/customizable_reagent_holder.dm @@ -206,7 +206,7 @@ if(isitem(atom_parent)) var/obj/item/item_parent = atom_parent if(ingredient.w_class > item_parent.w_class) - item_parent.w_class = ingredient.w_class + item_parent.update_weight_class(ingredient.w_class) atom_parent.name = "[custom_adjective()] [custom_type()] [initial(atom_parent.name)]" SEND_SIGNAL(atom_parent, COMSIG_ATOM_CUSTOMIZED, ingredient) SEND_SIGNAL(ingredient, COMSIG_ITEM_USED_AS_INGREDIENT, atom_parent) diff --git a/code/datums/components/deadchat_control.dm b/code/datums/components/deadchat_control.dm index 7517f35ff29..210ef26a052 100644 --- a/code/datums/components/deadchat_control.dm +++ b/code/datums/components/deadchat_control.dm @@ -61,7 +61,7 @@ /datum/component/deadchat_control/proc/deadchat_react(mob/source, message) SIGNAL_HANDLER - message = lowertext(message) + message = LOWER_TEXT(message) if(!inputs[message]) return @@ -162,7 +162,7 @@ */ /datum/component/deadchat_control/proc/waive_automute(mob/speaker, client/client, message, mute_type) SIGNAL_HANDLER - if(mute_type == MUTE_DEADCHAT && inputs[lowertext(message)]) + if(mute_type == MUTE_DEADCHAT && inputs[LOWER_TEXT(message)]) return WAIVE_AUTOMUTE_CHECK return NONE diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm index ded8b8c4161..a0b20858927 100644 --- a/code/datums/components/food/edible.dm +++ b/code/datums/components/food/edible.dm @@ -215,7 +215,7 @@ Behavior that's still missing from this component that original food items had t if(foodtypes) var/list/types = bitfield_to_list(foodtypes, FOOD_FLAGS) - examine_list += span_notice("It is [lowertext(english_list(types))].") + examine_list += span_notice("It is [LOWER_TEXT(english_list(types))].") var/quality = get_perceived_food_quality(user) if(quality > 0) diff --git a/code/datums/components/gps.dm b/code/datums/components/gps.dm index ceee193bf4a..7e52f00def7 100644 --- a/code/datums/components/gps.dm +++ b/code/datums/components/gps.dm @@ -50,7 +50,7 @@ GLOBAL_LIST_EMPTY(GPS_list) if(!emp_proof) RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp_act)) RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) - RegisterSignal(parent, COMSIG_CLICK_ALT, PROC_REF(on_AltClick)) + RegisterSignal(parent, COMSIG_CLICK_ALT, PROC_REF(on_click_alt)) ///Called on COMSIG_ITEM_ATTACK_SELF /datum/component/gps/item/proc/interact(datum/source, mob/user) @@ -85,10 +85,11 @@ GLOBAL_LIST_EMPTY(GPS_list) A.add_overlay("working") ///Calls toggletracking -/datum/component/gps/item/proc/on_AltClick(datum/source, mob/user) +/datum/component/gps/item/proc/on_click_alt(datum/source, mob/user) SIGNAL_HANDLER toggletracking(user) + return CLICK_ACTION_SUCCESS ///Toggles the tracking for the gps /datum/component/gps/item/proc/toggletracking(mob/user) @@ -153,7 +154,7 @@ GLOBAL_LIST_EMPTY(GPS_list) data["signals"] = signals return data -/datum/component/gps/item/ui_act(action, params) +/datum/component/gps/item/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() if(.) return @@ -162,7 +163,8 @@ GLOBAL_LIST_EMPTY(GPS_list) if("rename") var/atom/parentasatom = parent var/a = tgui_input_text(usr, "Enter the desired tag", "GPS Tag", gpstag, 20) - + if (QDELETED(ui) || ui.status != UI_INTERACTIVE) + return if (!a) return diff --git a/code/datums/components/infective.dm b/code/datums/components/infective.dm index 97df6342aeb..fc2081481d9 100644 --- a/code/datums/components/infective.dm +++ b/code/datums/components/infective.dm @@ -59,8 +59,10 @@ /datum/component/infective/proc/try_infect_eat(datum/source, mob/living/eater, mob/living/feeder) SIGNAL_HANDLER - if(!eater.has_quirk(/datum/quirk/deviant_tastes)) - eater.add_mood_event("disgust", /datum/mood_event/disgust/dirty_food) + if(HAS_TRAIT(eater, TRAIT_STRONG_STOMACH)) + return + + eater.add_mood_event("disgust", /datum/mood_event/disgust/dirty_food) if(is_weak && !prob(weak_infection_chance)) return @@ -76,6 +78,9 @@ /datum/component/infective/proc/try_infect_drink(datum/source, mob/living/drinker, mob/living/feeder) SIGNAL_HANDLER + if(HAS_TRAIT(drinker, TRAIT_STRONG_STOMACH)) + return + var/appendage_zone = feeder.held_items.Find(source) appendage_zone = appendage_zone == 0 ? BODY_ZONE_CHEST : appendage_zone % 2 ? BODY_ZONE_R_ARM : BODY_ZONE_L_ARM try_infect(feeder, appendage_zone) diff --git a/code/datums/components/martial_art_giver.dm b/code/datums/components/martial_art_giver.dm new file mode 100644 index 00000000000..1a0bfa9951a --- /dev/null +++ b/code/datums/components/martial_art_giver.dm @@ -0,0 +1,45 @@ +/// when equipped and unequipped this item gives a martial art +/datum/component/martial_art_giver + /// the style we give + var/datum/martial_art/style + +/datum/component/martial_art_giver/Initialize(style_type) + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + + style = new style_type() + style.allow_temp_override = FALSE + +/datum/component/martial_art_giver/RegisterWithParent() + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(equipped)) + RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(dropped)) + +/datum/component/martial_art_giver/UnregisterFromParent(datum/source) + UnregisterSignal(parent, list(COMSIG_ITEM_POST_EQUIPPED, COMSIG_ITEM_POST_UNEQUIP)) + var/obj/item/parent_item = parent + if(ismob(parent_item?.loc)) + UnregisterSignal(parent, list(COMSIG_MOB_MIND_TRANSFERRED_INTO, COMSIG_MOB_MIND_INITIALIZED, COMSIG_MOB_MIND_TRANSFERRED_OUT_OF)) + QDEL_NULL(style) + +/datum/component/martial_art_giver/proc/equipped(obj/item/source, mob/user, slot) + SIGNAL_HANDLER + if(!(source.slot_flags & slot)) + return + RegisterSignals(user, list(COMSIG_MOB_MIND_TRANSFERRED_INTO, COMSIG_MOB_MIND_INITIALIZED), PROC_REF(teach)) + RegisterSignal(user, COMSIG_MOB_MIND_TRANSFERRED_OUT_OF, PROC_REF(forget)) + teach(user) + +/datum/component/martial_art_giver/proc/dropped(obj/item/source, mob/user) + SIGNAL_HANDLER + forget(user) + UnregisterSignal(user, list(COMSIG_MOB_MIND_TRANSFERRED_INTO, COMSIG_MOB_MIND_INITIALIZED, COMSIG_MOB_MIND_TRANSFERRED_OUT_OF)) + +/datum/component/martial_art_giver/proc/teach(mob/source) + if(isnull(style)) + return + style.teach(source, TRUE) + +/datum/component/martial_art_giver/proc/forget(mob/source) + if(isnull(style)) + return + style.fully_remove(source) diff --git a/code/datums/components/material/material_container.dm b/code/datums/components/material/material_container.dm index 69f67d46df3..ffcf81feace 100644 --- a/code/datums/components/material/material_container.dm +++ b/code/datums/components/material/material_container.dm @@ -102,7 +102,7 @@ var/datum/material/M = I var/amt = materials[I] / SHEET_MATERIAL_AMOUNT if(amt) - examine_texts += span_notice("It has [amt] sheets of [lowertext(M.name)] stored.") + examine_texts += span_notice("It has [amt] sheets of [LOWER_TEXT(M.name)] stored.") /datum/component/material_container/vv_edit_var(var_name, var_value) var/old_flags = mat_container_flags @@ -678,6 +678,7 @@ while(sheet_amt > 0) //don't merge yet. we need to do stuff with it first var/obj/item/stack/sheet/new_sheets = new material.sheet_type(target, min(sheet_amt, MAX_STACK_SIZE), FALSE) + new_sheets.manufactured = TRUE count += new_sheets.amount //use material & deduct work needed use_amount_mat(new_sheets.amount * SHEET_MATERIAL_AMOUNT, material) diff --git a/code/datums/components/mirv.dm b/code/datums/components/mirv.dm index 0f41df1d288..52b4053babb 100644 --- a/code/datums/components/mirv.dm +++ b/code/datums/components/mirv.dm @@ -39,5 +39,5 @@ P.range = override_projectile_range P.preparePixelProjectile(shootat_turf, target) P.firer = firer // don't hit ourself that would be really annoying - P.impacted = list(target = TRUE) // don't hit the target we hit already with the flak + P.impacted = list(WEAKREF(target) = TRUE) // don't hit the target we hit already with the flak P.fire() diff --git a/code/datums/components/pellet_cloud.dm b/code/datums/components/pellet_cloud.dm index 52b0cc9c954..2b59305be14 100644 --- a/code/datums/components/pellet_cloud.dm +++ b/code/datums/components/pellet_cloud.dm @@ -281,7 +281,7 @@ P.original = target P.fired_from = parent P.firer = parent // don't hit ourself that would be really annoying - P.impacted = list(parent = TRUE) // don't hit the target we hit already with the flak + P.impacted = list(WEAKREF(parent) = TRUE) // don't hit the target we hit already with the flak P.suppressed = SUPPRESSED_VERY // set the projectiles to make no message so we can do our own aggregate message P.preparePixelProjectile(target, parent) RegisterSignal(P, COMSIG_PROJECTILE_SELF_ON_HIT, PROC_REF(pellet_hit)) diff --git a/code/datums/components/pet_commands/obeys_commands.dm b/code/datums/components/pet_commands/obeys_commands.dm index 2fceaa2b337..ec3a04c940a 100644 --- a/code/datums/components/pet_commands/obeys_commands.dm +++ b/code/datums/components/pet_commands/obeys_commands.dm @@ -72,6 +72,7 @@ return // Not our friend, can't boss us around INVOKE_ASYNC(src, PROC_REF(display_radial_menu), clicker) + return CLICK_ACTION_SUCCESS /// Actually display the radial menu and then do something with the result /datum/component/obeys_commands/proc/display_radial_menu(mob/living/clicker) diff --git a/code/datums/components/puzzgrid.dm b/code/datums/components/puzzgrid.dm index e91bcdb3002..d7e264f651f 100644 --- a/code/datums/components/puzzgrid.dm +++ b/code/datums/components/puzzgrid.dm @@ -280,12 +280,7 @@ var/list/answers = list() var/description -/// Debug verb for validating that all puzzgrids can be created successfully. -/// Locked behind a verb because it's fairly slow and memory intensive. -/client/proc/validate_puzzgrids() - set name = "Validate Puzzgrid Config" - set category = "Debug" - +ADMIN_VERB(validate_puzzgrids, R_DEBUG, "Validate Puzzgrid Config", "Validate the puzzgrid config to ensure it's set up correctly.", ADMIN_CATEGORY_DEBUG) var/line_number = 0 for (var/line in world.file2list(PUZZGRID_CONFIG)) @@ -296,16 +291,16 @@ var/line_json_decoded = safe_json_decode(line) if (isnull(line_json_decoded)) - to_chat(src, span_warning("Line [line_number] in puzzgrids.txt is not a JSON: [line]")) + to_chat(user, span_warning("Line [line_number] in puzzgrids.txt is not a JSON: [line]")) continue var/datum/puzzgrid/puzzgrid = new var/populate_result = puzzgrid.populate(line_json_decoded) if (populate_result != TRUE) - to_chat(src, span_warning("Line [line_number] in puzzgrids.txt is not formatted correctly: [populate_result]")) + to_chat(user, span_warning("Line [line_number] in puzzgrids.txt is not formatted correctly: [populate_result]")) - to_chat(src, span_notice("Validated. If you did not see any errors, you're in the clear.")) + to_chat(user, span_notice("Validated. If you did not see any errors, you're in the clear.")) #undef PUZZGRID_CONFIG #undef PUZZGRID_GROUP_COUNT diff --git a/code/datums/components/rotation.dm b/code/datums/components/rotation.dm index 7c55579c999..f872c6bfd69 100644 --- a/code/datums/components/rotation.dm +++ b/code/datums/components/rotation.dm @@ -59,6 +59,7 @@ /datum/component/simple_rotation/proc/rotate_left(datum/source, mob/user) SIGNAL_HANDLER rotate(user, ROTATION_COUNTERCLOCKWISE) + return CLICK_ACTION_SUCCESS /datum/component/simple_rotation/proc/rotate(mob/user, degrees) if(QDELETED(user)) diff --git a/code/datums/components/singularity.dm b/code/datums/components/singularity.dm index c1323d01e2f..56a6723f21f 100644 --- a/code/datums/components/singularity.dm +++ b/code/datums/components/singularity.dm @@ -360,8 +360,9 @@ target = potentially_closer //if we lost that target get a new one if(!target || QDELETED(target)) - target = find_new_target() - foreboding_nosebleed(target) + var/mob/living/new_target = find_new_target() + new_target?.ominous_nosebleed() + target = new_target return ..() ///Searches the living list for the closest target, and begins chasing them down. @@ -380,22 +381,6 @@ closest_target = target return closest_target -/// gives a little fluff warning that someone is being hunted. -/datum/component/singularity/bloodthirsty/proc/foreboding_nosebleed(mob/living/target) - if(!iscarbon(target)) - to_chat(target, span_warning("You feel a bit nauseous for just a moment.")) - return - var/mob/living/carbon/carbon_target = target - var/obj/item/bodypart/head = carbon_target.get_bodypart(BODY_ZONE_HEAD) - if(head) - if(HAS_TRAIT(carbon_target, TRAIT_NOBLOOD)) - to_chat(carbon_target, span_notice("You get a headache.")) - return - head.adjustBleedStacks(5) - carbon_target.visible_message(span_notice("[carbon_target] gets a nosebleed."), span_warning("You get a nosebleed.")) - return - to_chat(target, span_warning("You feel a bit nauseous for just a moment.")) - #undef CHANCE_TO_MOVE_TO_TARGET #undef CHANCE_TO_MOVE_TO_TARGET_BLOODTHIRSTY #undef CHANCE_TO_CHANGE_TARGET_BLOODTHIRSTY diff --git a/code/datums/components/style/style_meter.dm b/code/datums/components/style/style_meter.dm index 72688f41c52..c06fc35aca3 100644 --- a/code/datums/components/style/style_meter.dm +++ b/code/datums/components/style/style_meter.dm @@ -27,7 +27,7 @@ . = ..() . += span_notice("You feel like a multitool could be used on this.") -/obj/item/style_meter/interact_with_atom(atom/interacting_with, mob/living/user) +/obj/item/style_meter/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!istype(interacting_with, /obj/item/clothing/glasses)) return NONE @@ -38,7 +38,7 @@ 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_CLICK_ALT, PROC_REF(on_click_alt)) 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) @@ -90,14 +90,15 @@ /// Signal proc to remove from glasses -/obj/item/style_meter/proc/on_altclick(datum/source, mob/user) +/obj/item/style_meter/proc/on_click_alt(datum/source, mob/user) SIGNAL_HANDLER - if(istype(loc, /obj/item/clothing/glasses)) - clean_up() - forceMove(get_turf(src)) + if(!istype(loc, /obj/item/clothing/glasses)) + return CLICK_ACTION_BLOCKING - return COMPONENT_CANCEL_CLICK_ALT + clean_up() + forceMove(get_turf(src)) + return CLICK_ACTION_SUCCESS /obj/item/style_meter/multitool_act(mob/living/user, obj/item/tool) multitooled = !multitooled diff --git a/code/datums/components/surgery_initiator.dm b/code/datums/components/surgery_initiator.dm index cd2fcc2cff9..24bde4b4672 100644 --- a/code/datums/components/surgery_initiator.dm +++ b/code/datums/components/surgery_initiator.dm @@ -334,7 +334,7 @@ var/datum/surgery/procedure = new surgery.type(target, selected_zone, affecting_limb) ADD_TRAIT(target, TRAIT_ALLOWED_HONORBOUND_ATTACK, type) - target.balloon_alert(user, "starting \"[lowertext(procedure.name)]\"") + target.balloon_alert(user, "starting \"[LOWER_TEXT(procedure.name)]\"") user.visible_message( span_notice("[user] drapes [parent] over [target]'s [parse_zone(selected_zone)] to prepare for surgery."), diff --git a/code/datums/components/toggle_suit.dm b/code/datums/components/toggle_suit.dm index 596bf3b3252..c4a378a16de 100644 --- a/code/datums/components/toggle_suit.dm +++ b/code/datums/components/toggle_suit.dm @@ -20,7 +20,7 @@ src.base_icon_state = atom_parent.base_icon_state || atom_parent.icon_state /datum/component/toggle_icon/RegisterWithParent() - RegisterSignal(parent, COMSIG_CLICK_ALT, PROC_REF(on_alt_click)) + RegisterSignal(parent, COMSIG_CLICK_ALT, PROC_REF(on_click_alt)) RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) /datum/component/toggle_icon/UnregisterFromParent() @@ -34,7 +34,7 @@ * source - the atom being clicked on * user - the mob doing the click */ -/datum/component/toggle_icon/proc/on_alt_click(atom/source, mob/user) +/datum/component/toggle_icon/proc/on_click_alt(atom/source, mob/user) SIGNAL_HANDLER if(!isliving(user)) @@ -47,13 +47,14 @@ if(living_user.incapacitated()) source.balloon_alert(user, "you're incapacitated!") - return + return CLICK_ACTION_BLOCKING if(living_user.usable_hands <= 0) source.balloon_alert(user, "you don't have hands!") - return + return CLICK_ACTION_BLOCKING do_icon_toggle(source, living_user) + return CLICK_ACTION_SUCCESS /* * Signal proc for COMSIG_ATOM_EXAMINE. diff --git a/code/datums/components/transforming.dm b/code/datums/components/transforming.dm index e51c784657b..5276f45dc0a 100644 --- a/code/datums/components/transforming.dm +++ b/code/datums/components/transforming.dm @@ -212,7 +212,7 @@ source.attack_verb_simple = attack_verb_simple_on source.hitsound = hitsound_on - source.w_class = w_class_on + source.update_weight_class(w_class_on) source.icon_state = "[source.icon_state]_on" if(inhand_icon_change && source.inhand_icon_state) source.inhand_icon_state = "[source.inhand_icon_state]_on" @@ -241,7 +241,7 @@ source.attack_verb_simple = attack_verb_simple_off source.hitsound = initial(source.hitsound) - source.w_class = initial(source.w_class) + source.update_weight_class(initial(source.w_class)) source.icon_state = initial(source.icon_state) source.inhand_icon_state = initial(source.inhand_icon_state) if(ismob(source.loc)) diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index 5007d8caeb9..163de4867d5 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -378,8 +378,8 @@ /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))) + if(trim(LOWER_TEXT(new_ring_text)) != trim(LOWER_TEXT(unlock_code))) + if(trim(LOWER_TEXT(new_ring_text)) == trim(LOWER_TEXT(failsafe_code))) failsafe(user) return COMPONENT_STOP_RINGTONE_CHANGE return @@ -415,8 +415,8 @@ if(channel != RADIO_CHANNEL_UPLINK) return - if(!findtext(lowertext(message), lowertext(unlock_code))) - if(failsafe_code && findtext(lowertext(message), lowertext(failsafe_code))) + if(!findtext(LOWER_TEXT(message), LOWER_TEXT(unlock_code))) + if(failsafe_code && findtext(LOWER_TEXT(message), LOWER_TEXT(failsafe_code))) failsafe(user) // no point returning cannot radio, youre probably ded return locked = FALSE diff --git a/code/datums/diseases/advance/symptoms/fire.dm b/code/datums/diseases/advance/symptoms/fire.dm index f428abdb016..0708841fca0 100644 --- a/code/datums/diseases/advance/symptoms/fire.dm +++ b/code/datums/diseases/advance/symptoms/fire.dm @@ -71,7 +71,10 @@ if(prob(33.33)) living_mob.show_message(span_hear("You hear a crackling noise."), type = MSG_AUDIBLE) else - to_chat(living_mob, span_warning("[pick("You feel hot.", "You smell smoke.")]")) + if(HAS_TRAIT(living_mob, TRAIT_ANOSMIA)) //Anosmia quirk holder can't smell anything. + to_chat(living_mob, span_warning("You feel hot.")) + else + to_chat(living_mob, span_warning("[pick("You feel hot.", "You smell smoke.")]")) /* Alkali perspiration diff --git a/code/datums/diseases/tuberculosis.dm b/code/datums/diseases/tuberculosis.dm index de87cab6f3f..2a77195e311 100644 --- a/code/datums/diseases/tuberculosis.dm +++ b/code/datums/diseases/tuberculosis.dm @@ -18,11 +18,12 @@ if(!.) return + if(SPT_PROB(stage * 2, seconds_per_tick)) + affected_mob.emote("cough") + to_chat(affected_mob, span_danger("Your chest hurts.")) + switch(stage) if(2) - if(SPT_PROB(1, seconds_per_tick)) - affected_mob.emote("cough") - to_chat(affected_mob, span_danger("Your chest hurts.")) if(SPT_PROB(1, seconds_per_tick)) to_chat(affected_mob, span_danger("Your stomach violently rumbles!")) if(SPT_PROB(2.5, seconds_per_tick)) diff --git a/code/datums/elements/attack_zone_randomiser.dm b/code/datums/elements/attack_zone_randomiser.dm new file mode 100644 index 00000000000..35275e11a9b --- /dev/null +++ b/code/datums/elements/attack_zone_randomiser.dm @@ -0,0 +1,33 @@ +/// Pick a random attack zone before you attack something +/datum/element/attack_zone_randomiser + element_flags = ELEMENT_BESPOKE + argument_hash_start_idx = 2 + /// List of attack zones you can select, should be a subset of GLOB.all_body_zones + var/list/valid_attack_zones + +/datum/element/attack_zone_randomiser/Attach(datum/target, list/valid_attack_zones = GLOB.all_body_zones) + . = ..() + if (!isliving(target)) + return ELEMENT_INCOMPATIBLE + RegisterSignals(target, list(COMSIG_HOSTILE_PRE_ATTACKINGTARGET, COMSIG_LIVING_UNARMED_ATTACK), PROC_REF(randomise)) + src.valid_attack_zones = valid_attack_zones + +/datum/element/attack_zone_randomiser/Detach(datum/source) + UnregisterSignal(source, list (COMSIG_HOSTILE_PRE_ATTACKINGTARGET, COMSIG_LIVING_UNARMED_ATTACK)) + return ..() + +/// If we're attacking a carbon, pick a random defence zone +/datum/element/attack_zone_randomiser/proc/randomise(mob/living/source, atom/target) + SIGNAL_HANDLER + if (!iscarbon(target)) + return + var/mob/living/living_target = target + var/list/blacklist_zones = GLOB.all_body_zones - valid_attack_zones + var/new_zone = living_target.get_random_valid_zone(blacklisted_parts = blacklist_zones, bypass_warning = TRUE) + if (isnull(new_zone)) + new_zone = BODY_ZONE_CHEST + var/atom/movable/screen/zone_sel/zone_selector = source.hud_used?.zone_select + if (isnull(zone_selector)) + source.zone_selected = new_zone + else + zone_selector.set_selected_zone(new_zone, source, should_log = FALSE) diff --git a/code/datums/elements/backblast.dm b/code/datums/elements/backblast.dm index 169f961b3d3..8952afbfeaa 100644 --- a/code/datums/elements/backblast.dm +++ b/code/datums/elements/backblast.dm @@ -1,74 +1,43 @@ /** - * When attached to a gun and the gun is successfully fired, this element creates a "backblast" of fire and pain, like you'd find in a rocket launcher or recoilless rifle + * When attached to a gun and the gun is successfully fired, this element creates a "backblast", like you'd find in a rocket launcher or recoilless rifle * - * The backblast is simulated by a number of fire plumes, or invisible incendiary rounds that will torch anything they come across for a short distance, as well as knocking - * back nearby items. + * The backblast is simulated by a directional explosion 180 degrees from the direction of the fired projectile. */ /datum/element/backblast element_flags = ELEMENT_BESPOKE argument_hash_start_idx = 2 - /// How many "pellets" of backblast we're shooting backwards, spread between the angle defined in angle_spread - var/plumes - /// Assuming we don't just have 1 plume, this is the total angle we'll cover with the plumes, split down the middle directly behind the angle we fired at - var/angle_spread - /// How far each plume of fire will fly, assuming it doesn't hit a mob - var/range + /// Devasatation range of the explosion + var/dev_range + /// HGeavy damage range of the explosion + var/heavy_range + /// Light damage range of the explosion + var/light_range + /// Flame range of the explosion + var/flame_range + /// What angle do we want the backblast to cover + var/blast_angle -/datum/element/backblast/Attach(datum/target, plumes = 4, angle_spread = 48, range = 6) +/datum/element/backblast/Attach(datum/target, dev_range = 0, heavy_range = 0, light_range = 6, flame_range = 6, blast_angle = 60) . = ..() - if(!isgun(target) || plumes < 1 || angle_spread < 1 || range < 1) + if(!isgun(target) || dev_range < 0 || heavy_range < 0 || light_range < 0 || flame_range < 0 || blast_angle < 1) return ELEMENT_INCOMPATIBLE - src.plumes = plumes - src.angle_spread = angle_spread - src.range = range + src.dev_range = dev_range + src.heavy_range = heavy_range + src.light_range = light_range + src.flame_range = flame_range + src.blast_angle = blast_angle - if(plumes == 1) - RegisterSignal(target, COMSIG_GUN_FIRED, PROC_REF(gun_fired_simple)) - else - RegisterSignal(target, COMSIG_GUN_FIRED, PROC_REF(gun_fired)) + RegisterSignal(target, COMSIG_GUN_FIRED, PROC_REF(pew)) /datum/element/backblast/Detach(datum/source) if(source) UnregisterSignal(source, COMSIG_GUN_FIRED) return ..() -/// For firing multiple plumes behind us, we evenly spread out our projectiles based on the [angle_spread][/datum/element/backblast/var/angle_spread] and [number of plumes][/datum/element/backblast/var/plumes] -/datum/element/backblast/proc/gun_fired(obj/item/gun/weapon, mob/living/user, atom/target, params, zone_override) - SIGNAL_HANDLER - - if(!weapon.chambered || HAS_TRAIT(user, TRAIT_PACIFISM)) - return - - var/backwards_angle = get_angle(target, user) - var/starting_angle = SIMPLIFY_DEGREES(backwards_angle-(angle_spread * 0.5)) - var/iter_offset = angle_spread / plumes // how much we increment the angle for each plume - - for(var/i in 1 to plumes) - var/this_angle = SIMPLIFY_DEGREES(starting_angle + ((i - 1) * iter_offset)) - var/turf/target_turf = get_turf_in_angle(this_angle, get_turf(user), 10) - INVOKE_ASYNC(src, PROC_REF(pew), target_turf, weapon, user) - -/// If we're only firing one plume directly behind us, we don't need to bother with the loop or angles or anything -/datum/element/backblast/proc/gun_fired_simple(obj/item/gun/weapon, mob/living/user, atom/target, params, zone_override) - SIGNAL_HANDLER - - if(!weapon.chambered || HAS_TRAIT(user, TRAIT_PACIFISM)) - return - - var/backwards_angle = get_angle(target, user) - var/turf/target_turf = get_turf_in_angle(backwards_angle, get_turf(user), 10) - INVOKE_ASYNC(src, PROC_REF(pew), target_turf, weapon, user) - /// For firing an actual backblast pellet -/datum/element/backblast/proc/pew(turf/target_turf, obj/item/gun/weapon, mob/living/user) - //Shooting Code: - var/obj/projectile/bullet/incendiary/fire/backblast/P = new (get_turf(user)) - P.original = target_turf - P.range = range - P.fired_from = weapon - P.firer = user // don't hit ourself that would be really annoying - P.impacted = list(user = TRUE) // don't hit the target we hit already with the flak - P.preparePixelProjectile(target_turf, weapon) - P.fire() +/datum/element/backblast/proc/pew(obj/item/gun/weapon, mob/living/user, atom/target) + var/turf/origin = get_turf(weapon) + var/backblast_angle = get_angle(target, origin) + explosion(weapon, devastation_range = dev_range, heavy_impact_range = heavy_range, light_impact_range = light_range, flame_range = flame_range, adminlog = FALSE, protect_epicenter = TRUE, explosion_direction = backblast_angle, explosion_arc = blast_angle) diff --git a/code/datums/elements/decals/blood.dm b/code/datums/elements/decals/blood.dm index 7984939cddc..857b9e2b678 100644 --- a/code/datums/elements/decals/blood.dm +++ b/code/datums/elements/decals/blood.dm @@ -33,10 +33,7 @@ pic = blood_splatter return TRUE -/datum/element/decal/blood/proc/get_examine_name(datum/source, mob/user, list/override) +/datum/element/decal/blood/proc/get_examine_name(atom/source, mob/user, list/override) SIGNAL_HANDLER - var/atom/A = source - override[EXAMINE_POSITION_ARTICLE] = A.gender == PLURAL? "some" : "a" - override[EXAMINE_POSITION_BEFORE] = " blood-stained " - return COMPONENT_EXNAME_CHANGED + override[EXAMINE_POSITION_BEFORE] = "blood-stained" diff --git a/code/datums/elements/frozen.dm b/code/datums/elements/frozen.dm index 434968dd4d5..d112ef31b5f 100644 --- a/code/datums/elements/frozen.dm +++ b/code/datums/elements/frozen.dm @@ -63,7 +63,7 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0 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.obj_flags |= NO_DEBRIS_AFTER_DECONSTRUCTION // disable item spawning obj_target.deconstruct(FALSE) // call pre-deletion specialized code -- internals release gas etc /// signal handler for COMSIG_MOVABLE_MOVED that unfreezes our target if it moves onto an open turf thats hotter than diff --git a/code/datums/elements/living_limb_initialiser.dm b/code/datums/elements/living_limb_initialiser.dm new file mode 100644 index 00000000000..943b39dcf37 --- /dev/null +++ b/code/datums/elements/living_limb_initialiser.dm @@ -0,0 +1,19 @@ +/// Spawns a living limb mob inside a limb upon attachment if it doesn't have one +/datum/element/living_limb_initialiser + +/datum/element/living_limb_initialiser/Attach(atom/target) + . = ..() + if(!isbodypart(target)) + return ELEMENT_INCOMPATIBLE + RegisterSignal(target, COMSIG_BODYPART_CHANGED_OWNER, PROC_REF(try_animate_limb)) + +/datum/element/living_limb_initialiser/Detach(atom/target) + UnregisterSignal(target, COMSIG_BODYPART_CHANGED_OWNER) + return ..() + +/// Create a living limb mob inside the limb if it doesn't already have one +/datum/element/living_limb_initialiser/proc/try_animate_limb(obj/item/bodypart/part) + SIGNAL_HANDLER + if (locate(/mob/living/basic/living_limb_flesh) in part) + return + new /mob/living/basic/living_limb_flesh(part, part) diff --git a/code/datums/elements/poster_tearer.dm b/code/datums/elements/poster_tearer.dm new file mode 100644 index 00000000000..7a784a48615 --- /dev/null +++ b/code/datums/elements/poster_tearer.dm @@ -0,0 +1,45 @@ +/// Allows mobs with this element attached to just simply tear down any poster they desire to. +/datum/element/poster_tearer + element_flags = ELEMENT_BESPOKE + argument_hash_start_idx = 2 + /// The amount of time it takes to tear down a poster. + var/tear_time + /// Interaction key to use whilst tearing down a poster. + var/interaction_key + +/datum/element/poster_tearer/Attach(datum/target, tear_time = 2 SECONDS, interaction_key = null) + . = ..() + if (!isliving(target)) + return ELEMENT_INCOMPATIBLE + + src.tear_time = tear_time + src.interaction_key = interaction_key + + RegisterSignals(target, list(COMSIG_HOSTILE_PRE_ATTACKINGTARGET, COMSIG_LIVING_UNARMED_ATTACK), PROC_REF(on_attacked_poster)) + +/datum/element/poster_tearer/Detach(datum/source) + . = ..() + UnregisterSignal(source, list(COMSIG_HOSTILE_PRE_ATTACKINGTARGET, COMSIG_LIVING_UNARMED_ATTACK)) + +/// Try to tear up a poster on the wall +/datum/element/poster_tearer/proc/on_attacked_poster(mob/living/user, atom/target, proximity_flag) + SIGNAL_HANDLER + if(!istype(target, /obj/structure/sign/poster)) + return NONE // don't care we move on + + if(DOING_INTERACTION_WITH_TARGET(user, target) || (!isnull(interaction_key) && DOING_INTERACTION(user, interaction_key))) + user.balloon_alert(target, "busy!") + return COMPONENT_CANCEL_ATTACK_CHAIN + + INVOKE_ASYNC(src, PROC_REF(tear_it_down), user, target) + return COMPONENT_CANCEL_ATTACK_CHAIN + +/// Actually work on tearing down that poster +/datum/element/poster_tearer/proc/tear_it_down(mob/living/user, obj/structure/sign/poster/target) + if(!target.check_tearability(user)) // this proc will handle user feedback + return + + target.balloon_alert(user, "tearing down the poster...") + if(!do_after(user, tear_time, target, interaction_key = interaction_key)) // just in case the user actually enjoys art + return + target.tear_poster(user) diff --git a/code/datums/elements/ridable.dm b/code/datums/elements/ridable.dm index cbb6d7931f9..e68653b3d4a 100644 --- a/code/datums/elements/ridable.dm +++ b/code/datums/elements/ridable.dm @@ -197,3 +197,15 @@ to_chat(user, span_notice("You gently let go of [rider].")) return return rider + +/obj/item/riding_offhand/interact_with_atom(atom/movable/interacting_with, mob/living/user, list/modifiers) + if(!istype(interacting_with) || !interacting_with.can_buckle) + return NONE + if(rider == user) // Piggyback user + return ITEM_INTERACT_BLOCKING + + // Handles de-fireman carrying a mob and buckling them onto something (tables, etc) + var/mob/living/former_rider = rider + user.unbuckle_mob(former_rider) + former_rider.forceMove(get_turf(interacting_with)) + return interacting_with.mouse_buckle_handling(former_rider, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING diff --git a/code/datums/elements/strippable.dm b/code/datums/elements/strippable.dm index a8a45f54ecc..87524379523 100644 --- a/code/datums/elements/strippable.dm +++ b/code/datums/elements/strippable.dm @@ -283,10 +283,8 @@ source.log_message("had [item] put on them by [key_name(user)].", LOG_VICTIM, color="orange", log_globally=FALSE) /// A utility function for `/datum/strippable_item`s to start unequipping an item from a mob. -/proc/start_unequip_mob(obj/item/item, mob/source, mob/user, strip_delay) - //SKYRAT EDIT ADDITION - THIEVING GLOVES - //if (!do_after(user, strip_delay || item.strip_delay, source, interaction_key = REF(item))) - if (!do_after(user, (strip_delay || item.strip_delay) * (HAS_TRAIT(user, TRAIT_STICKY_FINGERS) ? THIEVING_GLOVES_STRIP_SLOWDOWN : NORMAL_STRIP_SLOWDOWN), source, interaction_key = REF(item))) +/proc/start_unequip_mob(obj/item/item, mob/source, mob/user, strip_delay, hidden = FALSE) + if (!do_after(user, (strip_delay || item.strip_delay) * (HAS_TRAIT(user, TRAIT_STICKY_FINGERS) ? THIEVING_GLOVES_STRIP_SLOWDOWN : NORMAL_STRIP_SLOWDOWN), source, interaction_key = REF(item), hidden = hidden)) // SKYRAT EDIT CHANGE - ORIGINAL: if (!do_after(user, strip_delay || item.strip_delay, source, interaction_key = REF(item), hidden = hidden)) return FALSE return TRUE diff --git a/code/datums/elements/tool_renaming.dm b/code/datums/elements/tool_renaming.dm new file mode 100644 index 00000000000..bd87f1d171c --- /dev/null +++ b/code/datums/elements/tool_renaming.dm @@ -0,0 +1,78 @@ +#define OPTION_RENAME "Rename" +#define OPTION_DESCRIPTION "Description" +#define OPTION_RESET "Reset" + +/** + * Renaming tool element + * + * When using this tool on an object with UNIQUE_RENAME, + * lets the user rename/redesc it. + */ +/datum/element/tool_renaming + +/datum/element/tool_renaming/Attach(datum/target) + . = ..() + if(!isitem(target)) + return ELEMENT_INCOMPATIBLE + + RegisterSignal(target, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(attempt_rename)) + +/datum/element/tool_renaming/Detach(datum/source) + . = ..() + UnregisterSignal(source, COMSIG_ITEM_INTERACTING_WITH_ATOM) + +/datum/element/tool_renaming/proc/attempt_rename(datum/source, mob/living/user, atom/interacting_with, list/modifiers) + SIGNAL_HANDLER + + if(!isobj(interacting_with)) + return NONE + + var/obj/renamed_obj = interacting_with + + if(!(renamed_obj.obj_flags & UNIQUE_RENAME)) + return NONE + + INVOKE_ASYNC(src, PROC_REF(async_rename), user, renamed_obj) + return ITEM_INTERACT_SUCCESS + +/datum/element/tool_renaming/proc/async_rename(mob/living/user, obj/renamed_obj) + var/custom_choice = tgui_input_list(user, "What would you like to edit?", "Customization", list(OPTION_RENAME, OPTION_DESCRIPTION, OPTION_RESET)) + if(QDELETED(renamed_obj) || !user.can_perform_action(renamed_obj) || isnull(custom_choice)) + return + + switch(custom_choice) + if(OPTION_RENAME) + var/old_name = renamed_obj.name + var/input = tgui_input_text(user, "What do you want to name [renamed_obj]?", "Object Name", "[old_name]", MAX_NAME_LEN) + if(QDELETED(renamed_obj) || !user.can_perform_action(renamed_obj)) + return + if(input == old_name || !input) + to_chat(user, span_notice("You changed [renamed_obj] to... well... [renamed_obj].")) + return + renamed_obj.AddComponent(/datum/component/rename, input, renamed_obj.desc) + to_chat(user, span_notice("You have successfully renamed \the [old_name] to [renamed_obj].")) + ADD_TRAIT(renamed_obj, TRAIT_WAS_RENAMED, RENAMING_TOOL_LABEL_TRAIT) + renamed_obj.update_appearance(UPDATE_NAME) + + if(OPTION_DESCRIPTION) + var/old_desc = renamed_obj.desc + var/input = tgui_input_text(user, "Describe [renamed_obj]", "Description", "[old_desc]", MAX_DESC_LEN) + if(QDELETED(renamed_obj) || !user.can_perform_action(renamed_obj)) + return + if(input == old_desc || !input) + to_chat(user, span_notice("You decide against changing [renamed_obj]'s description.")) + return + renamed_obj.AddComponent(/datum/component/rename, renamed_obj.name, input) + to_chat(user, span_notice("You have successfully changed [renamed_obj]'s description.")) + ADD_TRAIT(renamed_obj, TRAIT_WAS_RENAMED, RENAMING_TOOL_LABEL_TRAIT) + renamed_obj.update_appearance(UPDATE_DESC) + + if(OPTION_RESET) + qdel(renamed_obj.GetComponent(/datum/component/rename)) + to_chat(user, span_notice("You have successfully reset [renamed_obj]'s name and description.")) + REMOVE_TRAIT(renamed_obj, TRAIT_WAS_RENAMED, RENAMING_TOOL_LABEL_TRAIT) + renamed_obj.update_appearance(UPDATE_NAME | UPDATE_DESC) + +#undef OPTION_RENAME +#undef OPTION_DESCRIPTION +#undef OPTION_RESET diff --git a/code/datums/elements/watery_tile.dm b/code/datums/elements/watery_tile.dm new file mode 100644 index 00000000000..797eda39135 --- /dev/null +++ b/code/datums/elements/watery_tile.dm @@ -0,0 +1,21 @@ +/datum/element/watery_tile + element_flags = ELEMENT_DETACH_ON_HOST_DESTROY + +/datum/element/watery_tile/Attach(turf/target) + . = ..() + if(!isturf(target)) + return ELEMENT_INCOMPATIBLE + + RegisterSignal(target, COMSIG_ATOM_ENTERED, PROC_REF(extinguish_atom)) + +/datum/element/watery_tile/Detach(turf/source) + UnregisterSignal(source, COMSIG_ATOM_ENTERED) + return ..() + +/datum/element/watery_tile/proc/extinguish_atom(atom/source, atom/movable/entered) + SIGNAL_HANDLER + + entered.extinguish() + if(isliving(entered)) + var/mob/living/our_mob = entered + our_mob.adjust_wet_stacks(3) diff --git a/code/datums/greyscale/json_reader.dm b/code/datums/greyscale/json_reader.dm index ffe143c28fc..38286631fed 100644 --- a/code/datums/greyscale/json_reader.dm +++ b/code/datums/greyscale/json_reader.dm @@ -63,7 +63,7 @@ ) /datum/json_reader/blend_mode/ReadJson(value) - var/new_value = blend_modes[lowertext(value)] + var/new_value = blend_modes[LOWER_TEXT(value)] if(isnull(new_value)) CRASH("Blend mode expected but got '[value]'") return new_value diff --git a/code/datums/keybinding/admin.dm b/code/datums/keybinding/admin.dm index 80936aa41e7..1e94f71e58a 100644 --- a/code/datums/keybinding/admin.dm +++ b/code/datums/keybinding/admin.dm @@ -23,7 +23,7 @@ . = ..() if(.) return - user.admin_ghost() + SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/admin_ghost) return TRUE /datum/keybinding/admin/player_panel_new @@ -51,7 +51,7 @@ . = ..() if(.) return - user.togglebuildmodeself() + SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/build_mode_self) return TRUE /datum/keybinding/admin/stealthmode @@ -65,7 +65,7 @@ . = ..() if(.) return - user.stealth() + SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/stealth) return TRUE /datum/keybinding/admin/invisimin @@ -79,7 +79,7 @@ . = ..() if(.) return - user.invisimin() + SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/invisimin) return TRUE /datum/keybinding/admin/deadsay @@ -107,7 +107,7 @@ . = ..() if(.) return - user.deadmin() + SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/deadmin) return TRUE /datum/keybinding/admin/readmin @@ -135,5 +135,5 @@ . = ..() if(.) return - user.holder?.display_tags() + SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/display_tags) return TRUE diff --git a/code/datums/looping_sounds/item_sounds.dm b/code/datums/looping_sounds/item_sounds.dm index f8ed5d89b20..00fd3063e43 100644 --- a/code/datums/looping_sounds/item_sounds.dm +++ b/code/datums/looping_sounds/item_sounds.dm @@ -44,3 +44,7 @@ /datum/looping_sound/beesmoke mid_sounds = list('sound/weapons/beesmoke.ogg' = 1) volume = 5 + +/datum/looping_sound/zipline + mid_sounds = list('sound/weapons/zipline_mid.ogg' = 1) + volume = 5 diff --git a/code/datums/martial/boxing.dm b/code/datums/martial/boxing.dm index 8ef30db63aa..ec111fb3cf0 100644 --- a/code/datums/martial/boxing.dm +++ b/code/datums/martial/boxing.dm @@ -74,7 +74,6 @@ return ..() /obj/item/clothing/gloves/boxing - var/datum/martial_art/boxing/style /obj/item/clothing/gloves/boxing/Initialize(mapload) . = ..() @@ -85,18 +84,4 @@ slapcraft_recipes = slapcraft_recipe_list,\ ) - style = new() - style.allow_temp_override = FALSE - -/obj/item/clothing/gloves/boxing/Destroy() - QDEL_NULL(style) - return ..() - -/obj/item/clothing/gloves/boxing/equipped(mob/user, slot) - . = ..() - if(slot & ITEM_SLOT_GLOVES) - style.teach(user, TRUE) - -/obj/item/clothing/gloves/boxing/dropped(mob/user) - . = ..() - style.fully_remove(user) + AddComponent(/datum/component/martial_art_giver, /datum/martial_art/boxing) diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm index 66d092e886e..57e158cf669 100644 --- a/code/datums/martial/krav_maga.dm +++ b/code/datums/martial/krav_maga.dm @@ -208,26 +208,11 @@ //Krav Maga Gloves /obj/item/clothing/gloves/krav_maga - var/datum/martial_art/krav_maga/style clothing_traits = list(TRAIT_FAST_CUFFING) /obj/item/clothing/gloves/krav_maga/Initialize(mapload) . = ..() - style = new() - style.allow_temp_override = FALSE - -/obj/item/clothing/gloves/krav_maga/Destroy() - QDEL_NULL(style) - return ..() - -/obj/item/clothing/gloves/krav_maga/equipped(mob/user, slot) - . = ..() - if(slot & ITEM_SLOT_GLOVES) - style.teach(user, TRUE) - -/obj/item/clothing/gloves/krav_maga/dropped(mob/user) - . = ..() - style.fully_remove(user) + AddComponent(/datum/component/martial_art_giver, /datum/martial_art/krav_maga) /obj/item/clothing/gloves/krav_maga/sec//more obviously named, given to sec name = "krav maga gloves" diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index c55f95d4bd6..8116084127e 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -325,7 +325,7 @@ /obj/item/clothing/gloves/the_sleeping_carp name = "carp gloves" - desc = "This gloves are capable of making people use The Sleeping Carp." + desc = "These gloves are capable of making people use The Sleeping Carp." icon_state = "black" greyscale_colors = COLOR_BLACK cold_protection = HANDS @@ -333,26 +333,10 @@ heat_protection = HANDS max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE - var/datum/martial_art/the_sleeping_carp/style /obj/item/clothing/gloves/the_sleeping_carp/Initialize(mapload) . = ..() - style = new() - style.allow_temp_override = FALSE - -/obj/item/clothing/gloves/the_sleeping_carp/Destroy() - QDEL_NULL(style) - return ..() - -/obj/item/clothing/gloves/the_sleeping_carp/equipped(mob/user, slot) - . = ..() - if(slot & ITEM_SLOT_GLOVES) - style.teach(user, TRUE) - -/obj/item/clothing/gloves/the_sleeping_carp/dropped(mob/user) - . = ..() - if(!isnull(style)) - style.fully_remove(user) + AddComponent(/datum/component/martial_art_giver, /datum/martial_art/the_sleeping_carp) #undef STRONG_PUNCH_COMBO #undef LAUNCH_KICK_COMBO diff --git a/code/datums/martial/wrestling.dm b/code/datums/martial/wrestling.dm index 6969c3eeb9e..4bcaf02b2d5 100644 --- a/code/datums/martial/wrestling.dm +++ b/code/datums/martial/wrestling.dm @@ -490,22 +490,7 @@ If you make a derivative work from this code, you must include this notification /obj/item/storage/belt/champion/wrestling name = "Wrestling Belt" - var/datum/martial_art/wrestling/style /obj/item/storage/belt/champion/wrestling/Initialize(mapload) . = ..() - style = new() - style.allow_temp_override = FALSE - -/obj/item/storage/belt/champion/wrestling/Destroy() - QDEL_NULL(style) - return ..() - -/obj/item/storage/belt/champion/wrestling/equipped(mob/user, slot) - . = ..() - if(slot & ITEM_SLOT_BELT) - style.teach(user, TRUE) - -/obj/item/storage/belt/champion/wrestling/dropped(mob/user) - . = ..() - style.fully_remove(user) + AddComponent(/datum/component/martial_art_giver, /datum/martial_art/wrestling) diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index f6e64d57e71..45d72573978 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -2,8 +2,8 @@ /datum/material/iron name = "iron" desc = "Common iron ore often found in sedimentary and igneous layers of the crust." - color = "#878687" - greyscale_colors = "#878687" + color = "#B6BEC2" + greyscale_colors = "#B6BEC2" 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 @@ -22,8 +22,8 @@ /datum/material/glass name = "glass" desc = "Glass forged by melting sand." - color = "#88cdf1" - greyscale_colors = "#88cdf196" + color = "#6292AF" + greyscale_colors = "#6292AF" alpha = 150 categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) integrity_modifier = 0.1 @@ -39,6 +39,7 @@ armor_modifiers = list(MELEE = 0.2, BULLET = 0.2, ENERGY = 1, BIO = 0.2, FIRE = 1, ACID = 0.2) mineral_rarity = MATERIAL_RARITY_COMMON points_per_unit = 1 / SHEET_MATERIAL_AMOUNT + texture_layer_icon_state = "shine" /datum/material/glass/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5, sharpness = TRUE) //cronch @@ -63,8 +64,8 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/silver name = "silver" 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" + color = "#B5BCBB" + greyscale_colors = "#B5BCBB" 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 @@ -74,6 +75,7 @@ Unless you know what you're doing, only use the first three numbers. They're in beauty_modifier = 0.075 mineral_rarity = MATERIAL_RARITY_SEMIPRECIOUS points_per_unit = 16 / SHEET_MATERIAL_AMOUNT + texture_layer_icon_state = "shine" /datum/material/silver/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5) @@ -83,8 +85,8 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/gold name = "gold" desc = "Gold" - 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" + color = "#E6BB45" + greyscale_colors = "#E6BB45" strength_modifier = 1.2 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 @@ -96,6 +98,7 @@ Unless you know what you're doing, only use the first three numbers. They're in armor_modifiers = list(MELEE = 1.1, BULLET = 1.1, LASER = 1.15, ENERGY = 1.15, BOMB = 1, BIO = 1, FIRE = 0.7, ACID = 1.1) mineral_rarity = MATERIAL_RARITY_PRECIOUS points_per_unit = 18 / SHEET_MATERIAL_AMOUNT + texture_layer_icon_state = "shine" /datum/material/gold/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5) @@ -105,8 +108,8 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/diamond name = "diamond" 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" + color = "#C9D8F2" + greyscale_colors = "#C9D8F2" 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 @@ -128,8 +131,8 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/uranium name = "uranium" desc = "Uranium" - color = rgb(48, 237, 26) - greyscale_colors = rgb(48, 237, 26) + color = "#2C992C" + greyscale_colors = "#2C992C" 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 @@ -168,8 +171,8 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/plasma name = "plasma" 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" + color = "#BA3692" + greyscale_colors = "#BA3692" 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 @@ -200,8 +203,8 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/bluespace name = "bluespace crystal" desc = "Crystals with bluespace properties" - color = list(119/255, 217/255, 396/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) - greyscale_colors = "#4e7dffC8" + color = "#2E50B7" + greyscale_colors = "#2E50B7" alpha = 200 starlight_color = COLOR_BLUE categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_ITEM_MATERIAL = TRUE) @@ -213,6 +216,7 @@ Unless you know what you're doing, only use the first three numbers. They're in points_per_unit = 50 / SHEET_MATERIAL_AMOUNT tradable = TRUE tradable_base_quantity = MATERIAL_QUANTITY_EXOTIC + texture_layer_icon_state = "shine" /datum/material/bluespace/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.reagents.add_reagent(/datum/reagent/bluespace, rand(5, 8)) @@ -223,8 +227,8 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/bananium name = "bananium" 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" + 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 //It's literally perfect I can't change it + greyscale_colors = "#FFF269" 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 @@ -253,8 +257,8 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/titanium name = "titanium" desc = "Titanium" - color = "#b3c0c7" - greyscale_colors = "#b3c0c7" + color = "#EFEFEF" + greyscale_colors = "#EFEFEF" strength_modifier = 1.3 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 @@ -265,6 +269,7 @@ Unless you know what you're doing, only use the first three numbers. They're in beauty_modifier = 0.05 armor_modifiers = list(MELEE = 1.35, BULLET = 1.3, LASER = 1.3, ENERGY = 1.25, BOMB = 1.25, BIO = 1, FIRE = 0.7, ACID = 1) mineral_rarity = MATERIAL_RARITY_SEMIPRECIOUS + texture_layer_icon_state = "shine" /datum/material/titanium/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) victim.apply_damage(15, BRUTE, BODY_ZONE_HEAD, wound_bonus = 7) @@ -273,8 +278,8 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/runite name = "runite" desc = "Runite" - color = "#3F9995" - greyscale_colors = "#3F9995" + color = "#526F77" + greyscale_colors = "#526F77" strength_modifier = 1.3 categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/runite @@ -292,8 +297,8 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/plastic name = "plastic" desc = "Plastic" - color = "#caccd9" - greyscale_colors = "#caccd9" + color = "#BFB9AC" + greyscale_colors = "#BFB9AC" 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. @@ -321,8 +326,8 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/wood name = "wood" desc = "Flexible, durable, but flamable. Hard to come across in space." - color = "#bb8e53" - greyscale_colors = "#bb8e53" + color = "#855932" + greyscale_colors = "#855932" strength_modifier = 0.5 sheet_type = /obj/item/stack/sheet/mineral/wood categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) @@ -354,8 +359,8 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/adamantine name = "adamantine" desc = "A powerful material made out of magic, I mean science!" - color = "#6d7e8e" - greyscale_colors = "#6d7e8e" + color = "#2B7A74" + greyscale_colors = "#2B7A74" strength_modifier = 1.5 categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/adamantine @@ -426,11 +431,12 @@ Unless you know what you're doing, only use the first three numbers. They're in source_item?.reagents?.add_reagent(/datum/reagent/toxin/plasma, source_item.reagents.total_volume*(3/5)) return TRUE +// It's basically adamantine, but it isn't! /datum/material/metalhydrogen name = "Metal Hydrogen" desc = "Solid metallic hydrogen. Some say it should be impossible" - color = "#f2d5d7" - greyscale_colors = "#f2d5d796" + color = "#62708A" + greyscale_colors = "#62708A" alpha = 150 starlight_color = COLOR_MODERATE_BLUE categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) @@ -468,8 +474,8 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/sandstone name = "sandstone" desc = "Bialtaakid 'ant taerif ma hdha." - color = "#B77D31" - greyscale_colors = "#B77D31" + color = "#ECD5A8" + greyscale_colors = "#ECD5A8" categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/sandstone value_per_unit = 5 / SHEET_MATERIAL_AMOUNT @@ -498,8 +504,8 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/runedmetal name = "runed metal" desc = "Mir'ntrath barhah Nar'sie." - color = "#3C3434" - greyscale_colors = "#3C3434" + color = "#504742" + greyscale_colors = "#504742" categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/runed_metal value_per_unit = 1500 / SHEET_MATERIAL_AMOUNT @@ -515,8 +521,8 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/bronze name = "bronze" desc = "Clock Cult? Never heard of it." - color = "#92661A" - greyscale_colors = "#92661A" + color = "#876223" + greyscale_colors = "#876223" categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/bronze value_per_unit = 50 / SHEET_MATERIAL_AMOUNT diff --git a/code/datums/memory/_memory.dm b/code/datums/memory/_memory.dm index 0656d32006a..08a694616a3 100644 --- a/code/datums/memory/_memory.dm +++ b/code/datums/memory/_memory.dm @@ -392,7 +392,7 @@ if(istype(character, /datum/mind)) var/datum/mind/character_mind = character - return "\the [lowertext(initial(character_mind.assigned_role.title))]" + return "\the [LOWER_TEXT(initial(character_mind.assigned_role.title))]" // Generic result - mobs get "the guy", objs / turfs get "a thing" return ismob(character) ? "\the [character]" : "\a [character]" diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index 0cfb48f7a98..0e54c21e702 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -474,6 +474,11 @@ mood_change = -6 timeout = 5 MINUTES +/datum/mood_event/mallet_humiliation + description = "Getting hit by such a stupid weapon feels rather humiliating..." + mood_change = -3 + timeout = 10 SECONDS + ///Wizard cheesy grand finale - what everyone but the wizard gets /datum/mood_event/madness_despair description = "UNWORTHY, UNWORTHY, UNWORTHY!!!" diff --git a/code/datums/mood_events/needs_events.dm b/code/datums/mood_events/needs_events.dm index 72d789da1e0..dd5441476dc 100644 --- a/code/datums/mood_events/needs_events.dm +++ b/code/datums/mood_events/needs_events.dm @@ -66,7 +66,7 @@ mood_change = -12 /datum/mood_event/disgust/dirty_food - description = "It was too dirty to eat..." + description = "That was too dirty to eat..." mood_change = -6 timeout = 4 MINUTES diff --git a/code/datums/mutations/olfaction.dm b/code/datums/mutations/olfaction.dm index e014806233a..305f6d16e83 100644 --- a/code/datums/mutations/olfaction.dm +++ b/code/datums/mutations/olfaction.dm @@ -40,6 +40,10 @@ to_chat(owner, span_warning("You have no nose!")) return FALSE + if(HAS_TRAIT(living_cast_on, TRAIT_ANOSMIA)) //Anosmia quirk holders can't smell anything + to_chat(owner, span_warning("You can't smell!")) + return FALSE + return TRUE /datum/action/cooldown/spell/olfaction/cast(mob/living/cast_on) diff --git a/code/datums/quirks/_quirk.dm b/code/datums/quirks/_quirk.dm index 2f7c701e70f..05e62ab2726 100644 --- a/code/datums/quirks/_quirk.dm +++ b/code/datums/quirks/_quirk.dm @@ -167,7 +167,7 @@ * * default_location - If the item isn't possible to equip in a valid slot, this is a description of where the item was spawned. * * notify_player - If TRUE, adds strings to where_items_spawned list to be output to the player in [/datum/quirk/item_quirk/post_add()] */ -/datum/quirk/item_quirk/proc/give_item_to_holder(quirk_item, list/valid_slots, flavour_text = null, default_location = "at your feet", notify_player = TRUE) +/datum/quirk/item_quirk/proc/give_item_to_holder(obj/item/quirk_item, list/valid_slots, flavour_text = null, default_location = "at your feet", notify_player = TRUE) if(ispath(quirk_item)) quirk_item = new quirk_item(get_turf(quirk_holder)) diff --git a/code/datums/quirks/negative_quirks/all_nighter.dm b/code/datums/quirks/negative_quirks/all_nighter.dm index 7f9f051ecf7..f5288b82215 100644 --- a/code/datums/quirks/negative_quirks/all_nighter.dm +++ b/code/datums/quirks/negative_quirks/all_nighter.dm @@ -43,6 +43,8 @@ ///if we have bags and lost a head, remove them /datum/quirk/all_nighter/proc/on_removed_limb(datum/source, obj/item/bodypart/removed_limb, special, dismembered) + SIGNAL_HANDLER + if(bodypart_overlay && istype(removed_limb, /obj/item/bodypart/head)) remove_bags() diff --git a/code/datums/quirks/negative_quirks/anosmia.dm b/code/datums/quirks/negative_quirks/anosmia.dm new file mode 100644 index 00000000000..bbbf599aeaa --- /dev/null +++ b/code/datums/quirks/negative_quirks/anosmia.dm @@ -0,0 +1,9 @@ +/datum/quirk/item_quirk/anosmia + name = "Anosmia" + desc = "For some reason, you can't smell anything." + icon = FA_ICON_HEAD_SIDE_COUGH_SLASH + value = -2 + mob_trait = TRAIT_ANOSMIA + gain_text = span_notice("You find yourself unable to smell anything!") + lose_text = span_danger("Suddenly, you can smell again!") + medical_record_text = "Patient has lost their sensation of smell." diff --git a/code/datums/quirks/negative_quirks/insanity.dm b/code/datums/quirks/negative_quirks/insanity.dm index 56b56a53812..40e70f07b18 100644 --- a/code/datums/quirks/negative_quirks/insanity.dm +++ b/code/datums/quirks/negative_quirks/insanity.dm @@ -25,7 +25,7 @@ added_trauma.resilience = TRAUMA_RESILIENCE_ABSOLUTE added_trauma.name = name added_trauma.desc = medical_record_text - added_trauma.scan_desc = lowertext(name) + added_trauma.scan_desc = LOWER_TEXT(name) added_trauma.gain_text = null added_trauma.lose_text = null @@ -33,7 +33,7 @@ added_trama_ref = WEAKREF(added_trauma) /datum/quirk/insanity/post_add() - var/rds_policy = get_policy("[type]") || "Please note that your [lowertext(name)] does NOT give you any additional right to attack people or cause chaos." + var/rds_policy = get_policy("[type]") || "Please note that your [LOWER_TEXT(name)] does NOT give you any additional right to attack people or cause chaos." // I don't /think/ we'll need this, but for newbies who think "roleplay as insane" = "license to kill", it's probably a good thing to have. to_chat(quirk_holder, span_big(span_info(rds_policy))) diff --git a/code/datums/quirks/positive_quirks/strong_stomach.dm b/code/datums/quirks/positive_quirks/strong_stomach.dm new file mode 100644 index 00000000000..8c0a3f3b137 --- /dev/null +++ b/code/datums/quirks/positive_quirks/strong_stomach.dm @@ -0,0 +1,12 @@ +/datum/quirk/strong_stomach + name = "Strong Stomach" + desc = "You can eat food discarded on the ground without getting sick, and vomiting affects you less." + icon = FA_ICON_FACE_GRIN_BEAM_SWEAT + value = 4 + mob_trait = TRAIT_STRONG_STOMACH + gain_text = span_notice("You feel like you could eat anything!") + lose_text = span_danger("Looking at food on the ground makes you feel a little queasy.") + medical_record_text = "Patient has a stronger than average immune system...to food poisoning, at least." + mail_goodies = list( + /obj/item/reagent_containers/pill/ondansetron, + ) diff --git a/code/datums/station_traits/admin_panel.dm b/code/datums/station_traits/admin_panel.dm index 02eca48b54f..67669027c54 100644 --- a/code/datums/station_traits/admin_panel.dm +++ b/code/datums/station_traits/admin_panel.dm @@ -1,10 +1,6 @@ -/// Opens the station traits admin panel -/datum/admins/proc/station_traits_panel() - set name = "Modify Station Traits" - set category = "Admin.Events" - +ADMIN_VERB(station_traits_panel, R_FUN, "Modify Station Traits", "Modify the station traits for the next round.", ADMIN_CATEGORY_EVENTS) var/static/datum/station_traits_panel/station_traits_panel = new - station_traits_panel.ui_interact(usr) + station_traits_panel.ui_interact(user.mob) /datum/station_traits_panel var/static/list/future_traits diff --git a/code/datums/station_traits/negative_traits.dm b/code/datums/station_traits/negative_traits.dm index 610b79a40f1..2414681091a 100644 --- a/code/datums/station_traits/negative_traits.dm +++ b/code/datums/station_traits/negative_traits.dm @@ -149,7 +149,7 @@ /datum/station_trait/overflow_job_bureaucracy/proc/set_overflow_job_override(datum/source) SIGNAL_HANDLER var/datum/job/picked_job = pick(SSjob.get_valid_overflow_jobs()) - chosen_job_name = lowertext(picked_job.title) // like Chief Engineers vs like chief engineers + chosen_job_name = LOWER_TEXT(picked_job.title) // like Chief Engineers vs like chief engineers SSjob.set_overflow_role(picked_job.type) /datum/station_trait/slow_shuttle diff --git a/code/datums/status_effects/debuffs/fire_stacks.dm b/code/datums/status_effects/debuffs/fire_stacks.dm index 5bf8269bbbf..62f8c9ca24e 100644 --- a/code/datums/status_effects/debuffs/fire_stacks.dm +++ b/code/datums/status_effects/debuffs/fire_stacks.dm @@ -261,6 +261,7 @@ /datum/status_effect/fire_handler/fire_stacks/on_apply() . = ..() RegisterSignal(owner, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(add_fire_overlay)) + RegisterSignal(owner, COMSIG_ATOM_EXTINGUISH, PROC_REF(extinguish)) owner.update_appearance(UPDATE_OVERLAYS) /datum/status_effect/fire_handler/fire_stacks/proc/add_fire_overlay(mob/living/source, list/overlays) diff --git a/code/datums/status_effects/debuffs/speech_debuffs.dm b/code/datums/status_effects/debuffs/speech_debuffs.dm index 07bcd3c2543..4963a660b22 100644 --- a/code/datums/status_effects/debuffs/speech_debuffs.dm +++ b/code/datums/status_effects/debuffs/speech_debuffs.dm @@ -187,7 +187,7 @@ /datum/status_effect/speech/slurring/apply_speech(original_char) var/modified_char = original_char - var/lower_char = lowertext(modified_char) + var/lower_char = LOWER_TEXT(modified_char) if(prob(common_prob) && (lower_char in common_replacements)) var/to_replace = common_replacements[lower_char] if(islist(to_replace)) diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm index 42fad48509d..b1bacfbceab 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -207,6 +207,7 @@ RegisterSignal(parent, COMSIG_ATOM_EXAMINE_MORE, PROC_REF(handle_extra_examination)) RegisterSignal(parent, COMSIG_OBJ_DECONSTRUCT, PROC_REF(on_deconstruct)) RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp_act)) + RegisterSignal(parent, COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED, PROC_REF(contents_changed_w_class)) /** * Sets where items are physically being stored in the case it shouldn't be on the parent. @@ -401,7 +402,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) var/datum/storage/bigger_fish = parent.loc.atom_storage if(bigger_fish && bigger_fish.max_specific_storage < max_specific_storage) if(messages && user) - user.balloon_alert(user, "[lowertext(parent.loc.name)] is in the way!") + user.balloon_alert(user, "[LOWER_TEXT(parent.loc.name)] is in the way!") return FALSE if(isitem(parent)) @@ -915,7 +916,8 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) SIGNAL_HANDLER INVOKE_ASYNC(src, PROC_REF(open_storage), to_show) - return COMPONENT_NO_AFTERATTACK + if(display_contents) + return COMPONENT_NO_AFTERATTACK /// Opens the storage to the mob, showing them the contents to their UI. /datum/storage/proc/open_storage(mob/to_show) @@ -1092,3 +1094,14 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) var/matrix/old_matrix = parent.transform animate(parent, time = 1.5, loop = 0, transform = parent.transform.Scale(1.07, 0.9)) animate(time = 2, transform = old_matrix) + +/// Signal proc for [COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED] to drop items out of our storage if they're suddenly too heavy. +/datum/storage/proc/contents_changed_w_class(datum/source, obj/item/changed, old_w_class, new_w_class) + SIGNAL_HANDLER + + if(new_w_class <= max_specific_storage && new_w_class + get_total_weight() <= max_total_storage) + return + if(!attempt_remove(changed, parent.drop_location())) + return + + changed.visible_message(span_warning("[changed] falls out of [parent]!"), vision_distance = COMBAT_MESSAGE_RANGE) diff --git a/code/datums/storage/subtypes/fish_case.dm b/code/datums/storage/subtypes/fish_case.dm index dbbb15f47eb..82733d37ad9 100644 --- a/code/datums/storage/subtypes/fish_case.dm +++ b/code/datums/storage/subtypes/fish_case.dm @@ -24,25 +24,11 @@ var/obj/item/item_parent = parent if(arrived.w_class <= item_parent.w_class) return - item_parent.w_class = arrived.w_class - // Since we're changing weight class we need to check if our storage's loc's storage can still hold us - // in the future we need a generic solution to this to solve a bunch of other exploits - var/datum/storage/loc_storage = item_parent.loc.atom_storage - if(!isnull(loc_storage) && !loc_storage.can_insert(item_parent)) - item_parent.forceMove(item_parent.loc.drop_location()) - item_parent.visible_message(span_warning("[item_parent] spills out of [item_parent.loc] as it expands to hold [arrived]!"), vision_distance = 1) - return - - if(isliving(item_parent.loc)) - var/mob/living/living_loc = item_parent.loc - if((living_loc.get_slot_by_item(item_parent) & (ITEM_SLOT_RPOCKET|ITEM_SLOT_LPOCKET)) && item_parent.w_class > WEIGHT_CLASS_SMALL) - item_parent.forceMove(living_loc.drop_location()) - to_chat(living_loc, span_warning("[item_parent] drops out of your pockets as it expands to hold [arrived]!")) - return + item_parent.update_weight_class(arrived.w_class) /datum/storage/fish_case/handle_exit(datum/source, obj/item/gone) . = ..() if(!isitem(parent) || !istype(gone)) return var/obj/item/item_parent = parent - item_parent.w_class = initial(item_parent.w_class) + item_parent.update_weight_class(initial(item_parent.w_class)) diff --git a/code/datums/voice_of_god_command.dm b/code/datums/voice_of_god_command.dm index 052af9d060b..21d4f460617 100644 --- a/code/datums/voice_of_god_command.dm +++ b/code/datums/voice_of_god_command.dm @@ -35,7 +35,7 @@ GLOBAL_LIST_INIT(voice_of_god_commands, init_voice_of_god_commands()) if(!user.say(message, spans = span_list, sanitize = FALSE, ignore_spam = ignore_spam, forced = forced)) return - message = lowertext(message) + message = LOWER_TEXT(message) var/list/mob/living/listeners = list() //used to check if the speaker specified a name or a job to focus on @@ -299,7 +299,7 @@ GLOBAL_LIST_INIT(voice_of_god_commands, init_voice_of_god_commands()) for(var/mob/living/target as anything in listeners) var/to_say = user.name // 0.1% chance to be a smartass - if(findtext(lowertext(message), smartass_regex) && prob(0.1)) + if(findtext(LOWER_TEXT(message), smartass_regex) && prob(0.1)) to_say = "My name" addtimer(CALLBACK(target, TYPE_PROC_REF(/atom/movable, say), to_say), 0.5 SECONDS * iteration) iteration++ diff --git a/code/datums/wires/_wires.dm b/code/datums/wires/_wires.dm index 99438be18cc..cb7c3972993 100644 --- a/code/datums/wires/_wires.dm +++ b/code/datums/wires/_wires.dm @@ -258,7 +258,7 @@ return TRUE // Station blueprints do that too, but only if the wires are not randomized. - if(user.is_holding_item_of_type(/obj/item/areaeditor/blueprints) && !randomize) + if(user.is_holding_item_of_type(/obj/item/blueprints) && !randomize) return TRUE return FALSE diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index 00ac17b3b1f..9c3343b73ec 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -237,7 +237,7 @@ return FALSE if(user.grab_state == GRAB_PASSIVE) - to_chat(user, span_warning("You must have [victim] in an aggressive grab to manipulate [victim.p_their()] [lowertext(name)]!")) + to_chat(user, span_warning("You must have [victim] in an aggressive grab to manipulate [victim.p_their()] [LOWER_TEXT(name)]!")) return TRUE if(user.grab_state >= GRAB_AGGRESSIVE) diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm index 7304d21365c..ecefc56817c 100644 --- a/code/datums/wounds/pierce.dm +++ b/code/datums/wounds/pierce.dm @@ -73,7 +73,7 @@ if(victim.bodytemperature < (BODYTEMP_NORMAL - 10)) adjust_blood_flow(-0.1 * seconds_per_tick) if(SPT_PROB(2.5, seconds_per_tick)) - to_chat(victim, span_notice("You feel the [lowertext(name)] in your [limb.plaintext_zone] firming up from the cold!")) + to_chat(victim, span_notice("You feel the [LOWER_TEXT(name)] in your [limb.plaintext_zone] firming up from the cold!")) if(HAS_TRAIT(victim, TRAIT_BLOODY_MESS)) adjust_blood_flow(0.25 * seconds_per_tick) // old heparin used to just add +2 bleed stacks per tick, this adds 0.5 bleed flow to all open cuts which is probably even stronger as long as you can cut them first diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm index ad841856c64..e1b873cfec7 100644 --- a/code/game/atom/_atom.dm +++ b/code/game/atom/_atom.dm @@ -136,6 +136,9 @@ ///whether ghosts can see screentips on it var/ghost_screentips = FALSE + /// Flags to check for in can_perform_action. Used in alt-click checks + var/interaction_flags_click = NONE + /** * Top level of the destroy chain for most atoms * @@ -368,11 +371,6 @@ /atom/proc/return_analyzable_air() return null -///Check if this atoms eye is still alive (probably) -/atom/proc/check_eye(mob/user) - SIGNAL_HANDLER - return - /atom/proc/Bumped(atom/movable/bumped_atom) set waitfor = FALSE SEND_SIGNAL(src, COMSIG_ATOM_BUMPED, bumped_atom) diff --git a/code/game/atom/atom_color.dm b/code/game/atom/atom_color.dm index e5b52460aa0..2508e86f44d 100644 --- a/code/game/atom/atom_color.dm +++ b/code/game/atom/atom_color.dm @@ -42,15 +42,15 @@ * Can optionally be supplied with a range of priorities, IE only checking "washable" or above */ /atom/proc/is_atom_colour(looking_for_color, min_priority_index = 1, max_priority_index = COLOUR_PRIORITY_AMOUNT) - // make sure uppertext hex strings don't mess with lowertext hex strings - looking_for_color = lowertext(looking_for_color) + // make sure uppertext hex strings don't mess with LOWER_TEXT hex strings + looking_for_color = LOWER_TEXT(looking_for_color) if(!LAZYLEN(atom_colours)) // no atom colors list has been set up, just check the color var - return lowertext(color) == looking_for_color + return LOWER_TEXT(color) == looking_for_color for(var/i in min_priority_index to max_priority_index) - if(lowertext(atom_colours[i]) == looking_for_color) + if(LOWER_TEXT(atom_colours[i]) == looking_for_color) return TRUE return FALSE diff --git a/code/game/atom/atom_examine.dm b/code/game/atom/atom_examine.dm index 131aa6c8e9c..8df52eb9cb0 100644 --- a/code/game/atom/atom_examine.dm +++ b/code/game/atom/atom_examine.dm @@ -83,13 +83,16 @@ * [COMSIG_ATOM_GET_EXAMINE_NAME] signal */ /atom/proc/get_examine_name(mob/user) - . = "\a [src]" - var/list/override = list(gender == PLURAL ? "some" : "a", " ", "[name]") - if(article) - . = "[article] [src]" - override[EXAMINE_POSITION_ARTICLE] = article - if(SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override) & COMPONENT_EXNAME_CHANGED) - . = override.Join("") + var/list/override = list(article, null, "[name]") + SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override) + + if(!isnull(override[EXAMINE_POSITION_ARTICLE])) + override -= null // IF there is no "before", don't try to join it + return jointext(override, " ") + if(!isnull(override[EXAMINE_POSITION_BEFORE])) + override -= null // There is no article, don't try to join it + return "\a [jointext(override, " ")]" + return "\a [src]" ///Generate the full examine string of this atom (including icon for goonchat) /atom/proc/get_examine_string(mob/user, thats = FALSE) diff --git a/code/game/atom/atom_tool_acts.dm b/code/game/atom/atom_tool_acts.dm index 4b91f396095..b2cea26224b 100644 --- a/code/game/atom/atom_tool_acts.dm +++ b/code/game/atom/atom_tool_acts.dm @@ -4,15 +4,12 @@ * Handles non-combat iteractions of a tool on this atom, * such as using a tool on a wall to deconstruct it, * or scanning someone with a health analyzer - * - * This can be overridden to add custom item interactions to this atom - * - * Do not call this directly */ -/atom/proc/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) +/atom/proc/base_item_interaction(mob/living/user, obj/item/tool, list/modifiers) SHOULD_CALL_PARENT(TRUE) PROTECTED_PROC(TRUE) + var/is_right_clicking = LAZYACCESS(modifiers, RIGHT_CLICK) var/is_left_clicking = !is_right_clicking var/early_sig_return = NONE if(is_left_clicking) @@ -24,6 +21,12 @@ if(early_sig_return) return early_sig_return + var/self_interaction = is_left_clicking \ + ? item_interaction(user, tool, modifiers) \ + : item_interaction_secondary(user, tool, modifiers) + if(self_interaction) + return self_interaction + var/interact_return = is_left_clicking \ ? tool.interact_with_atom(src, user, modifiers) \ : tool.interact_with_atom_secondary(src, user, modifiers) @@ -85,6 +88,27 @@ SEND_SIGNAL(tool, COMSIG_TOOL_ATOM_ACTED_SECONDARY(tool_type), src) return act_result +/** + * Called when this atom has an item used on it. + * IE, a mob is clicking on this atom with an item. + * + * 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. + */ +/atom/proc/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + return NONE + +/** + * Called when this atom has an item used on it WITH RIGHT CLICK, + * IE, a mob is right clicking on this atom with an item. + * Default behavior has it run the same code as left click. + * + * 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. + */ +/atom/proc/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers) + return item_interaction(user, tool, modifiers) + /** * Called when this item is being used to interact with an atom, * IE, a mob is clicking on an atom with this item. diff --git a/code/game/atom/atom_vv.dm b/code/game/atom/atom_vv.dm index 8830a4af2f4..10a6cbff24a 100644 --- a/code/game/atom/atom_vv.dm +++ b/code/game/atom/atom_vv.dm @@ -67,14 +67,10 @@ message_admins(span_notice("[key_name(usr)] has added [amount] units of [chosen_id] to [src]")) if(href_list[VV_HK_TRIGGER_EXPLOSION]) - if(!check_rights(R_FUN)) - return - usr.client.cmd_admin_explosion(src) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/admin_explosion, src) if(href_list[VV_HK_TRIGGER_EMP]) - if(!check_rights(R_FUN)) - return - usr.client.cmd_admin_emp(src) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/admin_emp, src) if(href_list[VV_HK_SHOW_HIDDENPRINTS]) if(!check_rights(R_ADMIN)) diff --git a/code/game/atom/atoms_initializing_EXPENSIVE.dm b/code/game/atom/atoms_initializing_EXPENSIVE.dm index ea8bf9b125d..f76f00670d2 100644 --- a/code/game/atom/atoms_initializing_EXPENSIVE.dm +++ b/code/game/atom/atoms_initializing_EXPENSIVE.dm @@ -161,3 +161,5 @@ */ /atom/proc/LateInitialize() set waitfor = FALSE + SHOULD_CALL_PARENT(FALSE) + stack_trace("[src] ([type]) called LateInitialize but has nothing on it!") diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index d81f9306af4..a67e48f041c 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -6,6 +6,8 @@ GLOBAL_LIST_EMPTY(objectives) //SKYRAT EDIT ADDITION var/datum/team/team //An alternative to 'owner': a team. Use this when writing new code. var/name = "generic objective" //Name for admin prompts var/explanation_text = "Nothing" //What that person is supposed to do. + ///if this objective doesn't print failure or success in the roundend report + var/no_failure = FALSE ///name used in printing this objective (Objective #1) var/objective_name = "Objective" var/team_explanation_text //For when there are multiple owners. @@ -99,6 +101,8 @@ GLOBAL_LIST_EMPTY(objectives) //SKYRAT EDIT ADDITION /// Provides a string describing what a good job you did or did not do /datum/objective/proc/get_roundend_success_suffix() + if(no_failure) + return "" // Just print the objective with no success/fail evaluation, as it has no mechanical backing return check_completion() ? span_greentext("Success!") : span_redtext("Fail.") /datum/objective/proc/is_unique_objective(possible_target, dupe_search_range) @@ -356,6 +360,8 @@ GLOBAL_LIST_EMPTY(objectives) //SKYRAT EDIT ADDITION /datum/objective/protect/check_completion() var/obj/item/organ/internal/brain/brain_target + if(isnull(target)) + return FALSE if(human_check) brain_target = target.current?.get_organ_slot(ORGAN_SLOT_BRAIN) //Protect will always suceed when someone suicides @@ -405,7 +411,7 @@ GLOBAL_LIST_EMPTY(objectives) //SKYRAT EDIT ADDITION /datum/objective/jailbreak/detain/update_explanation_text() ..() if(target?.current) - explanation_text = "Ensure that [target.name], the [!target_role_type ? target.assigned_role.title : target.special_role] is delivered to nanotrasen alive and in custody." + explanation_text = "Ensure that [target.name], the [!target_role_type ? target.assigned_role.title : target.special_role] is delivered to Nanotrasen alive and in custody." else explanation_text = "Free objective." @@ -992,15 +998,13 @@ GLOBAL_LIST_EMPTY(possible_items) /datum/objective/custom name = "custom" admin_grantable = TRUE + no_failure = TRUE /datum/objective/custom/admin_edit(mob/admin) var/expl = stripped_input(admin, "Custom objective:", "Objective", explanation_text) if(expl) explanation_text = expl -/datum/objective/custom/get_roundend_success_suffix() - return "" // Just print the objective with no success/fail evaluation, as it has no mechanical backing - //Ideally this would be all of them but laziness and unusual subtypes /proc/generate_admin_objective_list() GLOB.admin_objective_list = list() diff --git a/code/game/gamemodes/objective_items.dm b/code/game/gamemodes/objective_items.dm index 64b3e4420cb..c88fa7f11b1 100644 --- a/code/game/gamemodes/objective_items.dm +++ b/code/game/gamemodes/objective_items.dm @@ -529,7 +529,7 @@ /datum/objective_item/steal/blueprints name = "the station blueprints" - targetitem = /obj/item/areaeditor/blueprints + targetitem = /obj/item/blueprints excludefromjob = list(JOB_CHIEF_ENGINEER) item_owner = list(JOB_CHIEF_ENGINEER) altitems = list(/obj/item/photo) @@ -537,11 +537,11 @@ difficulty = 3 steal_hint = "The blueprints of the station, found in the Chief Engineer's locker, or on their person. A picture may suffice." -/obj/item/areaeditor/blueprints/add_stealing_item_objective() - return add_item_to_steal(src, /obj/item/areaeditor/blueprints) +/obj/item/blueprints/add_stealing_item_objective() + return add_item_to_steal(src, /obj/item/blueprints) /datum/objective_item/steal/blueprints/check_special_completion(obj/item/I) - if(istype(I, /obj/item/areaeditor/blueprints)) + if(istype(I, /obj/item/blueprints)) return TRUE if(istype(I, /obj/item/photo)) var/obj/item/photo/P = I diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index d9ceac4f7f2..533c3aa1a42 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -184,12 +184,8 @@ return INITIALIZE_HINT_LATELOAD /obj/machinery/LateInitialize() - . = ..() - power_change() - if(use_power == NO_POWER_USE) - return - update_current_power_usage() - setup_area_power_relationship() + SHOULD_NOT_OVERRIDE(TRUE) + post_machine_initialize() /obj/machinery/Destroy(force) SSmachines.unregister_machine(src) @@ -200,6 +196,20 @@ return ..() +/** + * Called in LateInitialize meant to be the machine replacement to it + * This sets up power for the machine and requires parent be called, + * ensuring power works on all machines unless exempted with NO_POWER_USE. + * This is the proc to override if you want to do anything in LateInitialize. + */ +/obj/machinery/proc/post_machine_initialize() + SHOULD_CALL_PARENT(TRUE) + power_change() + if(use_power == NO_POWER_USE) + return + update_current_power_usage() + setup_area_power_relationship() + /** * proc to call when the machine starts to require power after a duration of not requiring power * sets up power related connections to its area if it exists and becomes area sensitive @@ -328,7 +338,6 @@ if(drop) dump_inventory_contents() update_appearance() - updateUsrDialog() /** * Drop every movable atom in the machine's contents list, including any components and circuit. @@ -413,7 +422,6 @@ if(target && !target.has_buckled_mobs() && (!isliving(target) || !mobtarget.buckled)) set_occupant(target) target.forceMove(src) - updateUsrDialog() update_appearance() ///updates the use_power var for this machine and updates its static power usage from its area to reflect the new value @@ -580,13 +588,15 @@ set_panel_open(!panel_open) /obj/machinery/can_interact(mob/user) + if(QDELETED(user)) + return FALSE + if((machine_stat & (NOPOWER|BROKEN)) && !(interaction_flags_machine & INTERACT_MACHINE_OFFLINE)) // Check if the machine is broken, and if we can still interact with it if so return FALSE if(SEND_SIGNAL(user, COMSIG_TRY_USE_MACHINE, src) & COMPONENT_CANT_USE_MACHINE_INTERACT) return FALSE - if(isAdminGhostAI(user)) return TRUE //the Gods have unlimited power and do not care for things such as range or blindness @@ -658,12 +668,10 @@ //Return a non FALSE value to interrupt attack_hand propagation to subtypes. /obj/machinery/interact(mob/user) - if(interaction_flags_machine & INTERACT_MACHINE_SET_MACHINE) - user.set_machine(src) update_last_used(user) - . = ..() + return ..() -/obj/machinery/ui_act(action, list/params) +/obj/machinery/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) add_fingerprint(usr) update_last_used(usr) if(HAS_AI_ACCESS(usr) && !GLOB.cameranet.checkTurfVis(get_turf(src))) //We check if they're an AI specifically here, so borgs can still access off-camera stuff. @@ -759,13 +767,14 @@ return update_last_used(user) -/obj/machinery/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) +/obj/machinery/base_item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(SEND_SIGNAL(user, COMSIG_TRY_USE_MACHINE, src) & COMPONENT_CANT_USE_MACHINE_TOOLS) - return ITEM_INTERACT_ANY_BLOCKER + return ITEM_INTERACT_BLOCKING + . = ..() - if(. & ITEM_INTERACT_BLOCKING) - return - update_last_used(user) + if(.) + update_last_used(user) + return . /obj/machinery/_try_interact(mob/user) if((interaction_flags_machine & INTERACT_MACHINE_WIRES_IF_OPEN) && panel_open && (attempt_wire_interaction(user) == WIRE_INTERACTION_BLOCK)) @@ -818,7 +827,7 @@ /obj/machinery/handle_deconstruct(disassembled = TRUE) SHOULD_NOT_OVERRIDE(TRUE) - if(obj_flags & NO_DECONSTRUCTION) + if(obj_flags & NO_DEBRIS_AFTER_DECONSTRUCTION) dump_inventory_contents() //drop stuff we consider important return //Just delete us, no need to call anything else. @@ -954,9 +963,6 @@ if(!istype(replacer_tool)) return FALSE - if(!replacer_tool.works_from_distance) - return FALSE - var/shouldplaysound = FALSE if(!component_parts) return FALSE diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 4fbfe2d37bf..1bdcba84967 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -388,15 +388,15 @@ drop_direction = direction balloon_alert(usr, "dropping [dir2text(drop_direction)]") -/obj/machinery/autolathe/AltClick(mob/user) - . = ..() - if(!drop_direction || !can_interact(user)) - return +/obj/machinery/autolathe/click_alt(mob/user) + if(!drop_direction) + return CLICK_ACTION_BLOCKING if(busy) balloon_alert(user, "busy printing!") - return + return CLICK_ACTION_SUCCESS balloon_alert(user, "drop direction reset") drop_direction = 0 + return CLICK_ACTION_SUCCESS /obj/machinery/autolathe/attackby(obj/item/attacking_item, mob/living/user, params) if(user.combat_mode) //so we can hit the machine diff --git a/code/game/machinery/barsigns.dm b/code/game/machinery/barsigns.dm index 006620ec5f4..e59de18ffcb 100644 --- a/code/game/machinery/barsigns.dm +++ b/code/game/machinery/barsigns.dm @@ -36,8 +36,9 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/barsign, 32) if(!istype(sign)) return + var/area/bar_area = get_area(src) if(change_area_name && sign.rename_area) - rename_area(src, sign.name) + rename_area(bar_area, sign.name) chosen_sign = sign update_appearance() @@ -152,7 +153,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/barsign, 32) /obj/machinery/barsign/attackby(obj/item/attacking_item, mob/user) - if(istype(attacking_item, /obj/item/areaeditor/blueprints) && !change_area_name) + if(istype(attacking_item, /obj/item/blueprints) && !change_area_name) if(!panel_open) balloon_alert(user, "open the panel first!") return TRUE diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index ed896cc7576..ca6562635ee 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -110,7 +110,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0) for(var/network_name in network) network -= network_name - network += lowertext(network_name) + network += LOWER_TEXT(network_name) GLOB.cameranet.cameras += src @@ -216,19 +216,19 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0) return if(. & EMP_PROTECT_SELF) return - if(prob(150 / severity)) - network = list() - GLOB.cameranet.removeCamera(src) - set_machine_stat(machine_stat | EMPED) - set_light(0) - emped++ //Increase the number of consecutive EMP's - update_appearance() - addtimer(CALLBACK(src, PROC_REF(post_emp_reset), emped, network), reset_time) - for(var/mob/M as anything in GLOB.player_list) - if (M.client?.eye == src) - M.unset_machine() - M.reset_perspective(null) - to_chat(M, span_warning("The screen bursts into static!")) + if(!prob(150 / severity)) + return + network = list() + GLOB.cameranet.removeCamera(src) + set_machine_stat(machine_stat | EMPED) + set_light(0) + emped++ //Increase the number of consecutive EMP's + update_appearance() + addtimer(CALLBACK(src, PROC_REF(post_emp_reset), emped, network), reset_time) + for(var/mob/M as anything in GLOB.player_list) + if (M.client?.eye == src) + M.reset_perspective(null) + to_chat(M, span_warning("The screen bursts into static!")) /obj/machinery/camera/proc/on_saboteur(datum/source, disrupt_duration) SIGNAL_HANDLER @@ -371,7 +371,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0) //I guess that doesn't matter since they can't use it anyway? for(var/mob/O as anything in GLOB.player_list) if (O.client?.eye == src) - O.unset_machine() O.reset_perspective(null) to_chat(O, span_warning("The screen bursts into static!")) diff --git a/code/game/machinery/camera/camera_construction.dm b/code/game/machinery/camera/camera_construction.dm index 48bf4ccabaa..15f22d02cbe 100644 --- a/code/game/machinery/camera/camera_construction.dm +++ b/code/game/machinery/camera/camera_construction.dm @@ -39,7 +39,7 @@ return ITEM_INTERACT_BLOCKING for(var/i in tempnetwork) tempnetwork -= i - tempnetwork += lowertext(i) + tempnetwork += LOWER_TEXT(i) camera_construction_state = CAMERA_STATE_FINISHED toggle_cam(user, displaymessage = FALSE) network = tempnetwork diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index bb9ef7d3fc5..2cd0506cbfd 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -66,7 +66,7 @@ /** * Autonaming camera - * Automatically names itself after the area it's in during LateInitialize, + * Automatically names itself after the area it's in during post_machine_initialize, * good for mappers who don't want to manually name them all. */ /obj/machinery/camera/autoname @@ -76,7 +76,7 @@ ..() return INITIALIZE_HINT_LATELOAD -/obj/machinery/camera/autoname/LateInitialize() +/obj/machinery/camera/autoname/post_machine_initialize() . = ..() var/static/list/autonames_in_areas = list() var/area/camera_area = get_area(src) diff --git a/code/game/machinery/civilian_bounties.dm b/code/game/machinery/civilian_bounties.dm index 2d284b17b67..1cb7ee1477e 100644 --- a/code/game/machinery/civilian_bounties.dm +++ b/code/game/machinery/civilian_bounties.dm @@ -60,7 +60,7 @@ pad_ref = WEAKREF(I.buffer) return TRUE -/obj/machinery/computer/piratepad_control/civilian/LateInitialize() +/obj/machinery/computer/piratepad_control/civilian/post_machine_initialize() . = ..() if(cargo_hold_id) for(var/obj/machinery/piratepad/civilian/C as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/piratepad/civilian)) @@ -163,11 +163,9 @@ inserted_scan_id.registered_account.bounties = null return inserted_scan_id.registered_account.civilian_bounty -/obj/machinery/computer/piratepad_control/civilian/AltClick(mob/user) - . = ..() - if(!Adjacent(user)) - return FALSE +/obj/machinery/computer/piratepad_control/civilian/click_alt(mob/user) id_eject(user, inserted_scan_id) + return CLICK_ACTION_SUCCESS /obj/machinery/computer/piratepad_control/civilian/ui_data(mob/user) var/list/data = list() diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm index 0749c79bb88..3ab4fef3fdb 100644 --- a/code/game/machinery/computer/_computer.dm +++ b/code/game/machinery/computer/_computer.dm @@ -128,12 +128,6 @@ new_frame.state = FRAME_COMPUTER_STATE_GLASSED new_frame.update_appearance(UPDATE_ICON_STATE) -/obj/machinery/computer/AltClick(mob/user) - . = ..() - if(!can_interact(user)) - return - if(!user.can_perform_action(src, ALLOW_SILICON_REACH) || !is_operational) - return /obj/machinery/computer/ui_interact(mob/user, datum/tgui/ui) SHOULD_CALL_PARENT(TRUE) diff --git a/code/game/machinery/computer/arcade/_arcade.dm b/code/game/machinery/computer/arcade/_arcade.dm new file mode 100644 index 00000000000..69994634fc3 --- /dev/null +++ b/code/game/machinery/computer/arcade/_arcade.dm @@ -0,0 +1,100 @@ +/obj/machinery/computer/arcade + name = "\proper the arcade cabinet which shouldn't exist" + desc = "This arcade cabinet has no games installed, and in fact, should not exist. \ + Report the location of this machine to your local diety." + icon_state = "arcade" + icon_keyboard = null + icon_screen = "invaders" + light_color = LIGHT_COLOR_GREEN + interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_REQUIRES_LITERACY + + ///If set, will dispense these as prizes instead of the default GLOB.arcade_prize_pool + ///Like prize pool, it must be a list of the prize and the weight of being selected. + var/list/prize_override + +/obj/machinery/computer/arcade/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(istype(tool, /obj/item/stack/arcadeticket)) + var/obj/item/stack/arcadeticket/tickets = tool + if(!tickets.use(2)) + balloon_alert(user, "need 2 tickets!") + return ITEM_INTERACT_BLOCKING + + prizevend(user) + balloon_alert(user, "prize claimed") + return ITEM_INTERACT_SUCCESS + + if(istype(tool, /obj/item/key/displaycase) || istype(tool, /obj/item/access_key)) + var/static/list/radial_menu_options + if(!radial_menu_options) + radial_menu_options = list( + "Reset Cabinet" = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_reset"), + "Cancel" = image(icon = 'icons/hud/radial.dmi', icon_state = "radial_close"), + ) + var/radial_reset_menu = show_radial_menu(user, src, radial_menu_options, require_near = TRUE) + if(radial_reset_menu != "Reset Cabinet") + return ITEM_INTERACT_BLOCKING + playsound(loc, 'sound/items/rattling_keys.ogg', 25, TRUE) + if(!do_after(user, 10 SECONDS, src)) + return ITEM_INTERACT_BLOCKING + balloon_alert(user, "cabinet reset") + reset_cabinet(user) + return ITEM_INTERACT_SUCCESS + + return NONE + +/obj/machinery/computer/arcade/screwdriver_act(mob/living/user, obj/item/I) + //you can't stop playing when you start. + if(obj_flags & EMAGGED) + return ITEM_INTERACT_BLOCKING + return ..() + +///Performs a factory reset of the cabinet and wipes all its stats. +/obj/machinery/computer/arcade/proc/reset_cabinet(mob/living/user) + SHOULD_CALL_PARENT(TRUE) + obj_flags &= ~EMAGGED + SStgui.update_uis(src) + +/obj/machinery/computer/arcade/emp_act(severity) + . = ..() + if((machine_stat & (NOPOWER|BROKEN)) || (. & EMP_PROTECT_SELF)) + return + + var/empprize = null + var/num_of_prizes = 0 + switch(severity) + if(1) + num_of_prizes = rand(1,4) + if(2) + num_of_prizes = rand(0,2) + for(var/i = num_of_prizes; i > 0; i--) + if(prize_override) + empprize = pick_weight(prize_override) + else + empprize = pick_weight(GLOB.arcade_prize_pool) + new empprize(loc) + explosion(src, devastation_range = -1, light_impact_range = 1 + num_of_prizes, flame_range = 1 + num_of_prizes) + +///Dispenses the proper prizes and gives them a positive mood event. If valid, has a small chance to give a pulse rifle. +/obj/machinery/computer/arcade/proc/prizevend(mob/living/user, prizes = 1) + SEND_SIGNAL(src, COMSIG_ARCADE_PRIZEVEND, user, prizes) + if(user.mind?.get_skill_level(/datum/skill/gaming) >= SKILL_LEVEL_LEGENDARY && HAS_TRAIT(user, TRAIT_GAMERGOD)) + visible_message("[user] inputs an intense cheat code!",\ + span_notice("You hear a flurry of buttons being pressed.")) + say("CODE ACTIVATED: EXTRA PRIZES.") + prizes *= 2 + for(var/i in 1 to prizes) + user.add_mood_event("arcade", /datum/mood_event/arcade) + if(prob(0.0001)) //1 in a million + new /obj/item/gun/energy/pulse/prize(src) + visible_message(span_notice("[src] dispenses.. woah, a gun! Way past cool."), span_notice("You hear a chime and a shot.")) + user.client.give_award(/datum/award/achievement/misc/pulse, user) + continue + + var/prizeselect + if(prize_override) + prizeselect = pick_weight(prize_override) + else + prizeselect = pick_weight(GLOB.arcade_prize_pool) + var/atom/movable/the_prize = new prizeselect(get_turf(src)) + playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3) + visible_message(span_notice("[src] dispenses [the_prize]!"), span_notice("You hear a chime and a clunk.")) diff --git a/code/game/machinery/computer/arcade/amputation.dm b/code/game/machinery/computer/arcade/amputation.dm new file mode 100644 index 00000000000..84a02af387a --- /dev/null +++ b/code/game/machinery/computer/arcade/amputation.dm @@ -0,0 +1,47 @@ +/obj/machinery/computer/arcade/amputation + name = "Mediborg's Amputation Adventure" + desc = "A picture of a blood-soaked medical cyborg flashes on the screen. \ + The mediborg has a speech bubble that says, \"Put your hand in the machine if you aren't a coward!\"" + icon_state = "arcade" + circuit = /obj/item/circuitboard/computer/arcade/amputation + interaction_flags_machine = NONE //borgs can't play, but the illiterate can. + +/obj/machinery/computer/arcade/amputation/attack_tk(mob/user) + return //that's a pretty damn big guillotine + +/obj/machinery/computer/arcade/amputation/attack_hand(mob/user, list/modifiers) + . = ..() + if(!iscarbon(user)) + return + to_chat(user, span_warning("You move your hand towards the machine, and begin to hesitate as a bloodied guillotine emerges from inside of it...")) + user.played_game() + var/obj/item/bodypart/chopchop = user.get_active_hand() + if(do_after(user, 5 SECONDS, target = src, extra_checks = CALLBACK(src, PROC_REF(do_they_still_have_that_hand), user, chopchop))) + playsound(src, 'sound/weapons/slice.ogg', 25, TRUE, -1) + to_chat(user, span_userdanger("The guillotine drops on your arm, and the machine sucks it in!")) + chopchop.dismember() + qdel(chopchop) + user.mind?.adjust_experience(/datum/skill/gaming, 100) + user.won_game() + playsound(src, 'sound/arcade/win.ogg', 50, TRUE) + new /obj/item/stack/arcadeticket((get_turf(src)), rand(6,10)) + to_chat(user, span_notice("[src] dispenses a handful of tickets!")) + return + if(!do_they_still_have_that_hand(user, chopchop)) + to_chat(user, span_warning("The guillotine drops, but your hand seems to be gone already!")) + playsound(src, 'sound/weapons/slice.ogg', 25, TRUE, -1) + else + to_chat(user, span_notice("You (wisely) decide against putting your hand in the machine.")) + user.lost_game() + +///Makes sure the user still has their starting hand, preventing the user from pulling the arm out and still getting prizes. +/obj/machinery/computer/arcade/amputation/proc/do_they_still_have_that_hand(mob/user, obj/item/bodypart/chopchop) + if(QDELETED(chopchop) || chopchop.owner != user) + return FALSE + return TRUE + +///Dispenses wrapped gifts instead of arcade prizes, also known as the ancap christmas tree +/obj/machinery/computer/arcade/amputation/festive + name = "Mediborg's Festive Amputation Adventure" + desc = "A picture of a blood-soaked medical cyborg wearing a Santa hat flashes on the screen. The mediborg has a speech bubble that says, \"Put your hand in the machine if you aren't a coward!\"" + prize_override = list(/obj/item/gift/anything = 1) diff --git a/code/game/machinery/computer/arcade/arcade.dm b/code/game/machinery/computer/arcade/arcade.dm deleted file mode 100644 index a4a22cc7542..00000000000 --- a/code/game/machinery/computer/arcade/arcade.dm +++ /dev/null @@ -1,713 +0,0 @@ -/* BUBBERSTATION CHANGE START: REDOES THE ARCADE PRIZE POOL. SEE MODULAR arcade.dm FILE FOR THE DROPTABLE. -GLOBAL_LIST_INIT(arcade_prize_pool, list( - /obj/item/storage/box/snappops = 2, - /obj/item/toy/talking/ai = 2, - /obj/item/toy/talking/codex_gigas = 2, - /obj/item/clothing/under/syndicate/tacticool = 2, - /obj/item/toy/sword = 2, - /obj/item/toy/gun = 2, - /obj/item/gun/ballistic/shotgun/toy/crossbow = 2, - /obj/item/storage/box/fakesyndiesuit = 2, - /obj/item/storage/crayons = 2, - /obj/item/toy/spinningtoy = 2, - /obj/item/toy/spinningtoy/dark_matter = 1, - /obj/item/toy/balloon/arrest = 2, - /obj/item/toy/mecha/ripley = 1, - /obj/item/toy/mecha/ripleymkii = 1, - /obj/item/toy/mecha/hauler = 1, - /obj/item/toy/mecha/clarke = 1, - /obj/item/toy/mecha/odysseus = 1, - /obj/item/toy/mecha/gygax = 1, - /obj/item/toy/mecha/durand = 1, - /obj/item/toy/mecha/savannahivanov = 1, - /obj/item/toy/mecha/phazon = 1, - /obj/item/toy/mecha/honk = 1, - /obj/item/toy/mecha/darkgygax = 1, - /obj/item/toy/mecha/mauler = 1, - /obj/item/toy/mecha/darkhonk = 1, - /obj/item/toy/mecha/deathripley = 1, - /obj/item/toy/mecha/reticence = 1, - /obj/item/toy/mecha/marauder = 1, - /obj/item/toy/mecha/seraph = 1, - /obj/item/toy/mecha/firefighter = 1, - /obj/item/toy/cards/deck = 2, - /obj/item/toy/nuke = 2, - /obj/item/toy/minimeteor = 2, - /obj/item/toy/redbutton = 2, - /obj/item/toy/talking/owl = 2, - /obj/item/toy/talking/griffin = 2, - /obj/item/coin/antagtoken = 2, - /obj/item/stack/tile/fakepit/loaded = 2, - /obj/item/stack/tile/eighties/loaded = 2, - /obj/item/toy/toy_xeno = 2, - /obj/item/storage/box/actionfigure = 1, - /obj/item/restraints/handcuffs/fake = 2, - /obj/item/grenade/chem_grenade/glitter/pink = 1, - /obj/item/grenade/chem_grenade/glitter/blue = 1, - /obj/item/grenade/chem_grenade/glitter/white = 1, - /obj/item/toy/eightball = 2, - /obj/item/toy/windup_toolbox = 2, - /obj/item/toy/clockwork_watch = 2, - /obj/item/toy/toy_dagger = 2, - /obj/item/extendohand/acme = 1, - /obj/item/hot_potato/harmless/toy = 1, - /obj/item/card/emagfake = 1, - /obj/item/clothing/shoes/wheelys = 2, - /obj/item/clothing/shoes/kindle_kicks = 2, - /obj/item/toy/plush/goatplushie = 2, - /obj/item/toy/plush/moth = 2, - /obj/item/toy/plush/pkplush = 2, - /obj/item/toy/plush/rouny = 2, - /obj/item/toy/plush/abductor = 2, - /obj/item/toy/plush/abductor/agent = 2, - /obj/item/toy/plush/shark = 2, - /obj/item/storage/belt/military/snack/full = 2, - /obj/item/toy/brokenradio = 2, - /obj/item/toy/braintoy = 2, - /obj/item/toy/eldritch_book = 2, - /obj/item/storage/box/heretic_box = 1, - /obj/item/toy/foamfinger = 2, - /obj/item/clothing/glasses/trickblindfold = 2, - /obj/item/clothing/mask/party_horn = 2, - /obj/item/storage/box/party_poppers = 2)) -BUBBERSTATION CHANGE END. */ - -/obj/machinery/computer/arcade - name = "\proper the arcade cabinet which shouldn't exist" - desc = "This arcade cabinet has no games installed, and in fact, should not exist. \ - Report the location of this machine to your local diety." - icon_state = "arcade" - icon_keyboard = null - icon_screen = "invaders" - light_color = LIGHT_COLOR_GREEN - interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON - var/list/prize_override - -/obj/machinery/computer/arcade/proc/Reset() - return - -/obj/machinery/computer/arcade/Initialize(mapload) - . = ..() - - Reset() - -/obj/machinery/computer/arcade/proc/prizevend(mob/living/user, prizes = 1) - SEND_SIGNAL(src, COMSIG_ARCADE_PRIZEVEND, user, prizes) - if(user.mind?.get_skill_level(/datum/skill/gaming) >= SKILL_LEVEL_LEGENDARY && HAS_TRAIT(user, TRAIT_GAMERGOD)) - visible_message("[user] inputs an intense cheat code!",\ - span_notice("You hear a flurry of buttons being pressed.")) - say("CODE ACTIVATED: EXTRA PRIZES.") - prizes *= 2 - for(var/i in 1 to prizes) - user.add_mood_event("arcade", /datum/mood_event/arcade) - if(prob(0.0001)) //1 in a million - new /obj/item/gun/energy/pulse/prize(src) - visible_message(span_notice("[src] dispenses.. woah, a gun! Way past cool."), span_notice("You hear a chime and a shot.")) - user.client.give_award(/datum/award/achievement/misc/pulse, user) - return - - var/prizeselect - if(prize_override) - prizeselect = pick_weight(prize_override) - else - //BUBBERSTATION CHANGE START: BETTER PRIZES. - prizeselect = pick_weight(GLOB.arcade_prize_pool) - while(islist(prizeselect)) - prizeselect = pick_weight(prizeselect) - //BUBBERSTATION CHANGE END: BETTER PRIZES. - var/atom/movable/the_prize = new prizeselect(get_turf(src)) - playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3) - visible_message(span_notice("[src] dispenses [the_prize]!"), span_notice("You hear a chime and a clunk.")) - -/obj/machinery/computer/arcade/emp_act(severity) - . = ..() - var/override = FALSE - if(prize_override) - override = TRUE - - if(machine_stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF) - return - - var/empprize = null - var/num_of_prizes = 0 - switch(severity) - if(1) - num_of_prizes = rand(1,4) - if(2) - num_of_prizes = rand(0,2) - for(var/i = num_of_prizes; i > 0; i--) - if(override) - empprize = pick_weight(prize_override) - else - //BUBBERSTATION CHANGE START: BETTER PRIZES. - empprize = pick_weight(GLOB.arcade_prize_pool) - while(islist(empprize)) - empprize = pick_weight(empprize) - //BUBBERSTATION CHANGE END: BETTER PRIZES. - new empprize(loc) - explosion(src, devastation_range = -1, light_impact_range = 1+num_of_prizes, flame_range = 1+num_of_prizes) - -/obj/machinery/computer/arcade/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) - . = ..() - if(. & ITEM_INTERACT_ANY_BLOCKER) - return . - if(!istype(tool, /obj/item/stack/arcadeticket)) - return . - - var/obj/item/stack/arcadeticket/tickets = tool - // BUBBER EDIT START - MAKES MACHINES USE 1 TICKET - if(!tickets.use(1)) - balloon_alert(user, "need 1 tickets!") - return ITEM_INTERACT_BLOCKING - //BUBBER EDIT END - - prizevend(user) - balloon_alert(user, "prize claimed") - return ITEM_INTERACT_SUCCESS - -// ** BATTLE ** // -/obj/machinery/computer/arcade/battle - name = "arcade machine" - desc = "Does not support Pinball." - icon_state = "arcade" - circuit = /obj/item/circuitboard/computer/arcade/battle - - interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_SET_MACHINE // we don't need to be literate to play video games fam - - var/enemy_name = "Space Villain" - ///Enemy health/attack points - var/enemy_hp = 100 - var/enemy_mp = 40 - ///Temporary message, for attack messages, etc - var/temp = "

Winners don't use space drugs

" - ///the list of passive skill the enemy currently has. the actual passives are added in the enemy_setup() proc - var/list/enemy_passive - ///if all the enemy's weakpoints have been triggered becomes TRUE - var/finishing_move = FALSE - ///linked to passives, when it's equal or above the max_passive finishing move will become TRUE - var/pissed_off = 0 - ///the number of passives the enemy will start with - var/max_passive = 3 - ///weapon wielded by the enemy, the shotgun doesn't count. - var/chosen_weapon - - ///Player health - var/player_hp = 85 - ///player magic points - var/player_mp = 20 - ///used to remember the last three move of the player before this turn. - var/list/last_three_move - ///if the enemy or player died. restart the game when TRUE - var/gameover = FALSE - ///the player cannot make any move while this is set to TRUE. should only TRUE during enemy turns. - var/blocked = FALSE - ///used to clear the enemy_action proc timer when the game is restarted - var/timer_id - ///weapon used by the enemy, pure fluff.for certain actions - var/list/weapons - ///unique to the emag mode, acts as a time limit where the player dies when it reaches 0. - var/bomb_cooldown = 19 - - -///creates the enemy base stats for a new round along with the enemy passives -/obj/machinery/computer/arcade/battle/proc/enemy_setup(player_skill) - player_hp = 85 - player_mp = 20 - enemy_hp = 100 - enemy_mp = 40 - gameover = FALSE - blocked = FALSE - finishing_move = FALSE - pissed_off = 0 - last_three_move = null - - enemy_passive = list("short_temper" = TRUE, "poisonous" = TRUE, "smart" = TRUE, "shotgun" = TRUE, "magical" = TRUE, "chonker" = TRUE) - for(var/i = LAZYLEN(enemy_passive); i > max_passive; i--) //we'll remove passives from the list until we have the number of passive we want - var/picked_passive = pick(enemy_passive) - LAZYREMOVE(enemy_passive, picked_passive) - - if(LAZYACCESS(enemy_passive, "chonker")) - enemy_hp += 20 - - if(LAZYACCESS(enemy_passive, "shotgun")) - chosen_weapon = "shotgun" - else if(weapons) - chosen_weapon = pick(weapons) - else - chosen_weapon = "null gun" //if the weapons list is somehow empty, shouldn't happen but runtimes are sneaky bastards. - - if(player_skill) - player_hp += player_skill * 2 - - -/obj/machinery/computer/arcade/battle/Reset() - max_passive = 3 - var/name_action - var/name_part1 - var/name_part2 - - if(check_holidays(HALLOWEEN)) - name_action = pick_list(ARCADE_FILE, "rpg_action_halloween") - name_part1 = pick_list(ARCADE_FILE, "rpg_adjective_halloween") - name_part2 = pick_list(ARCADE_FILE, "rpg_enemy_halloween") - weapons = strings(ARCADE_FILE, "rpg_weapon_halloween") - else if(check_holidays(CHRISTMAS)) - name_action = pick_list(ARCADE_FILE, "rpg_action_xmas") - name_part1 = pick_list(ARCADE_FILE, "rpg_adjective_xmas") - name_part2 = pick_list(ARCADE_FILE, "rpg_enemy_xmas") - weapons = strings(ARCADE_FILE, "rpg_weapon_xmas") - else if(check_holidays(VALENTINES)) - name_action = pick_list(ARCADE_FILE, "rpg_action_valentines") - name_part1 = pick_list(ARCADE_FILE, "rpg_adjective_valentines") - name_part2 = pick_list(ARCADE_FILE, "rpg_enemy_valentines") - weapons = strings(ARCADE_FILE, "rpg_weapon_valentines") - else - name_action = pick_list(ARCADE_FILE, "rpg_action") - name_part1 = pick_list(ARCADE_FILE, "rpg_adjective") - name_part2 = pick_list(ARCADE_FILE, "rpg_enemy") - weapons = strings(ARCADE_FILE, "rpg_weapon") - - enemy_name = ("The " + name_part1 + " " + name_part2) - name = (name_action + " " + enemy_name) - - enemy_setup(0) //in the case it's reset we assume the player skill is 0 because the VOID isn't a gamer - - -/obj/machinery/computer/arcade/battle/ui_interact(mob/user) - . = ..() - screen_setup(user) - - -///sets up the main screen for the user -/obj/machinery/computer/arcade/battle/proc/screen_setup(mob/user) - var/dat = "Close" - dat += "

[enemy_name]

" - - dat += "[temp]" - dat += "
Health: [player_hp] | Magic: [player_mp] | Enemy Health: [enemy_hp]
" - - if (gameover) - dat += "
New Game" - else - dat += "
Light attack" - dat += "
Defend" - dat += "
Counter attack" - dat += "
Power attack" - - dat += "
" - if(user.client) //mainly here to avoid a runtime when the player gets gibbed when losing the emag mode. - var/datum/browser/popup = new(user, "arcade", "Space Villain 2000") - popup.set_content(dat) - popup.open() - - -/obj/machinery/computer/arcade/battle/Topic(href, href_list) - if(..()) - return - var/gamerSkill = 0 - if(usr?.mind) - gamerSkill = usr.mind.get_skill_level(/datum/skill/gaming) - - usr.played_game() - - if (!blocked && !gameover) - var/attackamt = rand(5,7) + rand(0, gamerSkill) - - if(finishing_move) //time to bonk that fucker,cuban pete will sometime survive a finishing move. - attackamt *= 100 - - //light attack suck absolute ass but it doesn't cost any MP so it's pretty good to finish an enemy off - if (href_list["attack"]) - temp = "

you do quick jab for [attackamt] of damage!

" - enemy_hp -= attackamt - arcade_action(usr,"attack",attackamt) - - //defend lets you gain back MP and take less damage from non magical attack. - else if(href_list["defend"]) - temp = "

you take a defensive stance and gain back 10 mp!

" - player_mp += 10 - arcade_action(usr,"defend",attackamt) - playsound(src, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3) - - //mainly used to counter short temper and their absurd damage, will deal twice the damage the player took of a non magical attack. - else if(href_list["counter_attack"] && player_mp >= 10) - temp = "

you prepare yourself to counter the next attack!

" - player_mp -= 10 - arcade_action(usr,"counter_attack",attackamt) - playsound(src, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3) - - else if(href_list["counter_attack"] && player_mp < 10) - temp = "

you don't have the mp necessary to counter attack and defend yourself instead

" - player_mp += 10 - arcade_action(usr,"defend",attackamt) - playsound(src, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3) - - //power attack deals twice the amount of damage but is really expensive MP wise, mainly used with combos to get weakpoints. - else if (href_list["power_attack"] && player_mp >= 20) - temp = "

You attack [enemy_name] with all your might for [attackamt * 2] damage!

" - enemy_hp -= attackamt * 2 - player_mp -= 20 - arcade_action(usr,"power_attack",attackamt) - - else if(href_list["power_attack"] && player_mp < 20) - temp = "

You don't have the mp necessary for a power attack and settle for a light attack!

" - enemy_hp -= attackamt - arcade_action(usr,"attack",attackamt) - - if (href_list["close"]) - usr.unset_machine() - usr << browse(null, "window=arcade") - - else if (href_list["newgame"]) //Reset everything - temp = "

New Round

" - - if(obj_flags & EMAGGED) - Reset() - obj_flags &= ~EMAGGED - - enemy_setup(gamerSkill) - screen_setup(usr) - - - add_fingerprint(usr) - return - - -///happens after a player action and before the enemy turn. the enemy turn will be cancelled if there's a gameover. -/obj/machinery/computer/arcade/battle/proc/arcade_action(mob/user,player_stance,attackamt) - screen_setup(user) - blocked = TRUE - if(player_stance == "attack" || player_stance == "power_attack") - if(attackamt > 40) - playsound(src, 'sound/arcade/boom.ogg', 50, TRUE, extrarange = -3) - else - playsound(src, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3) - - timer_id = addtimer(CALLBACK(src, PROC_REF(enemy_action),player_stance,user),1 SECONDS,TIMER_STOPPABLE) - gameover_check(user) - - -///the enemy turn, the enemy's action entirely depend on their current passive and a teensy tiny bit of randomness -/obj/machinery/computer/arcade/battle/proc/enemy_action(player_stance,mob/user) - var/list/list_temp = list() - - switch(LAZYLEN(last_three_move)) //we keep the last three action of the player in a list here - if(0 to 2) - LAZYADD(last_three_move, player_stance) - if(3) - for(var/i in 1 to 2) - last_three_move[i] = last_three_move[i + 1] - last_three_move[3] = player_stance - - if(4 to INFINITY) - last_three_move = null //this shouldn't even happen but we empty the list if it somehow goes above 3 - - var/enemy_stance - var/attack_amount = rand(8,10) //making the attack amount not vary too much so that it's easier to see if the enemy has a shotgun - - if(player_stance == "defend") - attack_amount -= 5 - - //if emagged, cuban pete will set up a bomb acting up as a timer. when it reaches 0 the player fucking dies - if(obj_flags & EMAGGED) - switch(bomb_cooldown--) - if(18) - list_temp += "

[enemy_name] takes two valve tank and links them together, what's he planning?

" - if(15) - list_temp += "

[enemy_name] adds a remote control to the tan- ho god is that a bomb?

" - if(12) - list_temp += "

[enemy_name] throws the bomb next to you, you'r too scared to pick it up.

" - if(6) - list_temp += "

[enemy_name]'s hand brushes the remote linked to the bomb, your heart skipped a beat.

" - if(2) - list_temp += "

[enemy_name] is going to press the button! It's now or never!

" - if(0) - player_hp -= attack_amount * 1000 //hey it's a maxcap we might as well go all in - - //yeah I used the shotgun as a passive, you know why? because the shotgun gives +5 attack which is pretty good - if(LAZYACCESS(enemy_passive, "shotgun")) - if(weakpoint_check("shotgun","defend","defend","power_attack")) - list_temp += "

You manage to disarm [enemy_name] with a surprise power attack and shoot him with his shotgun until it runs out of ammo!

" - enemy_hp -= 10 - chosen_weapon = "empty shotgun" - else - attack_amount += 5 - - //heccing chonker passive, only gives more HP at the start of a new game but has one of the hardest weakpoint to trigger. - if(LAZYACCESS(enemy_passive, "chonker")) - if(weakpoint_check("chonker","power_attack","power_attack","power_attack")) - list_temp += "

After a lot of power attacks you manage to tip over [enemy_name] as they fall over their enormous weight

" - enemy_hp -= 30 - - //smart passive trait, mainly works in tandem with other traits, makes the enemy unable to be counter_attacked - if(LAZYACCESS(enemy_passive, "smart")) - if(weakpoint_check("smart","defend","defend","attack")) - list_temp += "

[enemy_name] is confused by your illogical strategy!

" - attack_amount -= 5 - - else if(attack_amount >= player_hp) - player_hp -= attack_amount - list_temp += "

[enemy_name] figures out you are really close to death and finishes you off with their [chosen_weapon]!

" - enemy_stance = "attack" - - else if(player_stance == "counter_attack") - list_temp += "

[enemy_name] is not taking your bait.

" - if(LAZYACCESS(enemy_passive, "short_temper")) - list_temp += "However controlling their hatred of you still takes a toll on their mental and physical health!" - enemy_hp -= 5 - enemy_mp -= 5 - enemy_stance = "defensive" - - //short temper passive trait, gets easily baited into being counter attacked but will bypass your counter when low on HP - if(LAZYACCESS(enemy_passive, "short_temper")) - if(weakpoint_check("short_temper","counter_attack","counter_attack","counter_attack")) - list_temp += "

[enemy_name] is getting frustrated at all your counter attacks and throws a tantrum!

" - enemy_hp -= attack_amount - - else if(player_stance == "counter_attack") - if(!(LAZYACCESS(enemy_passive, "smart")) && enemy_hp > 30) - list_temp += "

[enemy_name] took the bait and allowed you to counter attack for [attack_amount * 2] damage!

" - player_hp -= attack_amount - enemy_hp -= attack_amount * 2 - enemy_stance = "attack" - - else if(enemy_hp <= 30) //will break through the counter when low enough on HP even when smart. - list_temp += "

[enemy_name] is getting tired of your tricks and breaks through your counter with their [chosen_weapon]!

" - player_hp -= attack_amount - enemy_stance = "attack" - - else if(!enemy_stance) - var/added_temp - - if(rand()) - added_temp = "you for [attack_amount + 5] damage!" - player_hp -= attack_amount + 5 - enemy_stance = "attack" - else - added_temp = "the wall, breaking their skull in the process and losing [attack_amount] hp!" //[enemy_name] you have a literal dent in your skull - enemy_hp -= attack_amount - enemy_stance = "attack" - - list_temp += "

[enemy_name] grits their teeth and charge right into [added_temp]

" - - //in the case none of the previous passive triggered, Mainly here to set an enemy stance for passives that needs it like the magical passive. - if(!enemy_stance) - enemy_stance = pick("attack","defensive") - if(enemy_stance == "attack") - player_hp -= attack_amount - list_temp += "

[enemy_name] attacks you for [attack_amount] points of damage with their [chosen_weapon]

" - if(player_stance == "counter_attack") - enemy_hp -= attack_amount * 2 - list_temp += "

You counter [enemy_name]'s attack and deal [attack_amount * 2] points of damage!

" - - if(enemy_stance == "defensive" && enemy_mp < 15) - list_temp += "

[enemy_name] take some time to get some mp back!

" - enemy_mp += attack_amount - - else if (enemy_stance == "defensive" && enemy_mp >= 15 && !(LAZYACCESS(enemy_passive, "magical"))) - list_temp += "

[enemy_name] quickly heal themselves for 5 hp!

" - enemy_mp -= 15 - enemy_hp += 5 - - //magical passive trait, recharges MP nearly every turn it's not blasting you with magic. - if(LAZYACCESS(enemy_passive, "magical")) - if(player_mp >= 50) - list_temp += "

the huge amount of magical energy you have acumulated throws [enemy_name] off balance!

" - enemy_mp = 0 - LAZYREMOVE(enemy_passive, "magical") - pissed_off++ - - else if(LAZYACCESS(enemy_passive, "smart") && player_stance == "counter_attack" && enemy_mp >= 20) - list_temp += "

[enemy_name] blasts you with magic from afar for 10 points of damage before you can counter!

" - player_hp -= 10 - enemy_mp -= 20 - - else if(enemy_hp >= 20 && enemy_mp >= 40 && enemy_stance == "defensive") - list_temp += "

[enemy_name] Blasts you with magic from afar!

" - enemy_mp -= 40 - player_hp -= 30 - enemy_stance = "attack" - - else if(enemy_hp < 20 && enemy_mp >= 20 && enemy_stance == "defensive") //it's a pretty expensive spell so they can't spam it that much - list_temp += "

[enemy_name] heal themselves with magic and gain back 20 hp!

" - enemy_hp += 20 - enemy_mp -= 30 - else - list_temp += "

[enemy_name]'s magical nature lets them get some mp back!

" - enemy_mp += attack_amount - - //poisonous passive trait, while it's less damage added than the shotgun it acts up even when the enemy doesn't attack at all. - if(LAZYACCESS(enemy_passive, "poisonous")) - if(weakpoint_check("poisonous","attack","attack","attack")) - list_temp += "

your flurry of attack throws back the poisonnous gas at [enemy_name] and makes them choke on it!

" - enemy_hp -= 5 - else - list_temp += "

the stinky breath of [enemy_name] hurts you for 3 hp!

" - player_hp -= 3 - - //if all passive's weakpoint have been triggered, set finishing_move to TRUE - if(pissed_off >= max_passive && !finishing_move) - list_temp += "

You have weakened [enemy_name] enough for them to show their weak point, you will do 10 times as much damage with your next attack!

" - finishing_move = TRUE - - playsound(src, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3) - - temp = list_temp.Join() - gameover_check(user) - screen_setup(user) - blocked = FALSE - - -/obj/machinery/computer/arcade/battle/proc/gameover_check(mob/user) - var/xp_gained = 0 - if(enemy_hp <= 0) - if(!gameover) - if(timer_id) - deltimer(timer_id) - timer_id = null - if(player_hp <= 0) - player_hp = 1 //let's just pretend the enemy didn't kill you so not both the player and enemy look dead. - gameover = TRUE - blocked = FALSE - temp = "

[enemy_name] has fallen! Rejoice!

" - playsound(loc, 'sound/arcade/win.ogg', 50, TRUE) - - if(obj_flags & EMAGGED) - new /obj/effect/spawner/newbomb/plasma(loc, /obj/item/assembly/timer) - new /obj/item/clothing/head/collectable/petehat(loc) - message_admins("[ADMIN_LOOKUPFLW(usr)] has outbombed Cuban Pete and been awarded a bomb.") - usr.log_message("outbombed Cuban Pete and has been awarded a bomb.", LOG_GAME) - Reset() - obj_flags &= ~EMAGGED - xp_gained += 100 - else - new /obj/item/stack/arcadeticket((get_turf(src)), 2) - to_chat(user, span_notice("[src] dispenses 2 tickets!")) - xp_gained += 50 - SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("win", (obj_flags & EMAGGED ? "emagged":"normal"))) - user.won_game() - - else if(player_hp <= 0) - if(timer_id) - deltimer(timer_id) - timer_id = null - gameover = TRUE - temp = "

You have been crushed! GAME OVER

" - playsound(loc, 'sound/arcade/lose.ogg', 50, TRUE) - xp_gained += 10//pity points - if(obj_flags & EMAGGED) - var/mob/living/living_user = user - if (istype(living_user)) - living_user.investigate_log("has been gibbed by an emagged Orion Trail game.", INVESTIGATE_DEATHS) - living_user.gib(DROP_ALL_REMAINS) - SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "hp", (obj_flags & EMAGGED ? "emagged":"normal"))) - user.lost_game() - - if(gameover) - user?.mind?.adjust_experience(/datum/skill/gaming, xp_gained+1)//always gain at least 1 point of XP - - -///used to check if the last three move of the player are the one we want in the right order and if the passive's weakpoint has been triggered yet -/obj/machinery/computer/arcade/battle/proc/weakpoint_check(passive,first_move,second_move,third_move) - if(LAZYLEN(last_three_move) < 3) - return FALSE - - if(last_three_move[1] == first_move && last_three_move[2] == second_move && last_three_move[3] == third_move && LAZYACCESS(enemy_passive, passive)) - LAZYREMOVE(enemy_passive, passive) - pissed_off++ - return TRUE - else - return FALSE - - -/obj/machinery/computer/arcade/battle/Destroy() - enemy_passive = null - weapons = null - last_three_move = null - return ..() //well boys we did it, lists are no more - -/obj/machinery/computer/arcade/battle/examine_more(mob/user) - . = ..() - . += span_notice("You notice some writing scribbled on the side of [src]...") - . += "\t[span_info("smart -> defend, defend, light attack")]" - . += "\t[span_info("shotgun -> defend, defend, power attack")]" - . += "\t[span_info("short temper -> counter, counter, counter")]" - . += "\t[span_info("poisonous -> light attack, light attack, light attack")]" - . += "\t[span_info("chonker -> power attack, power attack, power attack")]" - . += "\t[span_info("magical -> defend until outmagiced")]" - return . - -/obj/machinery/computer/arcade/battle/emag_act(mob/user, obj/item/card/emag/emag_card) - if(obj_flags & EMAGGED) - return FALSE - - balloon_alert(user, "hard mode enabled") - to_chat(user, span_warning("A mesmerizing Rhumba beat starts playing from the arcade machine's speakers!")) - temp = "

If you die in the game, you die for real!

" - max_passive = 6 - bomb_cooldown = 18 - var/gamerSkill = 0 - if(user?.mind) - gamerSkill = user.mind.get_skill_level(/datum/skill/gaming) - enemy_setup(gamerSkill) - enemy_hp += 100 //extra HP just to make cuban pete even more bullshit - player_hp += 30 //the player will also get a few extra HP in order to have a fucking chance - - screen_setup(user) - gameover = FALSE - - obj_flags |= EMAGGED - - enemy_name = "Cuban Pete" - name = "Outbomb Cuban Pete" - - updateUsrDialog() - return TRUE - -// ** AMPUTATION ** // - -/obj/machinery/computer/arcade/amputation - name = "Mediborg's Amputation Adventure" - desc = "A picture of a blood-soaked medical cyborg flashes on the screen. The mediborg has a speech bubble that says, \"Put your hand in the machine if you aren't a coward!\"" - icon_state = "arcade" - circuit = /obj/item/circuitboard/computer/arcade/amputation - -/obj/machinery/computer/arcade/amputation/attack_tk(mob/user) - return //that's a pretty damn big guillotine - -/obj/machinery/computer/arcade/amputation/attack_hand(mob/user, list/modifiers) - . = ..() - if(!iscarbon(user)) - return - to_chat(user, span_warning("You move your hand towards the machine, and begin to hesitate as a bloodied guillotine emerges from inside of it...")) - user.played_game() - var/obj/item/bodypart/chopchop = user.get_active_hand() - if(do_after(user, 5 SECONDS, target = src, extra_checks = CALLBACK(src, PROC_REF(do_they_still_have_that_hand), user, chopchop))) - playsound(src, 'sound/weapons/slice.ogg', 25, TRUE, -1) - to_chat(user, span_userdanger("The guillotine drops on your arm, and the machine sucks it in!")) - chopchop.dismember() - qdel(chopchop) - user.mind?.adjust_experience(/datum/skill/gaming, 100) - user.won_game() - playsound(src, 'sound/arcade/win.ogg', 50, TRUE) - new /obj/item/stack/arcadeticket((get_turf(src)), rand(6,10)) - to_chat(user, span_notice("[src] dispenses a handful of tickets!")) - return - else if(!do_they_still_have_that_hand(user, chopchop)) - to_chat(user, span_warning("The guillotine drops, but your hand seems to be gone already!")) - playsound(src, 'sound/weapons/slice.ogg', 25, TRUE, -1) - else - to_chat(user, span_notice("You (wisely) decide against putting your hand in the machine.")) - user.lost_game() - -///Makes sure the user still has their starting hand. -/obj/machinery/computer/arcade/amputation/proc/do_they_still_have_that_hand(mob/user, obj/item/bodypart/chopchop) - if(QDELETED(chopchop) || chopchop.owner != user) //No pulling your arm out of the machine! - return FALSE - return TRUE - - -/obj/machinery/computer/arcade/amputation/festive //dispenses wrapped gifts instead of arcade prizes, also known as the ancap christmas tree - name = "Mediborg's Festive Amputation Adventure" - desc = "A picture of a blood-soaked medical cyborg wearing a Santa hat flashes on the screen. The mediborg has a speech bubble that says, \"Put your hand in the machine if you aren't a coward!\"" - prize_override = list(/obj/item/gift/anything = 1) diff --git a/code/game/machinery/computer/arcade/battle.dm b/code/game/machinery/computer/arcade/battle.dm new file mode 100644 index 00000000000..63d2808c773 --- /dev/null +++ b/code/game/machinery/computer/arcade/battle.dm @@ -0,0 +1,559 @@ +///How many enemies needs to be defeated until the 'Boss' of the stage appears. +#define WORLD_ENEMY_BOSS 2 +///The default amount of EXP you gain from killing an enemy, modifiers stacked on top of this. +#define DEFAULT_EXP_GAIN 50 +///The default cost to purchase an item. Sleeping at the Inn is half of this. +#define DEFAULT_ITEM_PRICE 30 + +///The max HP the player can have at any time. +#define PLAYER_MAX_HP 100 +///The max MP the player can have at any time. +#define PLAYER_MAX_MP 50 +///The default cost of a spell, in MP. Defending will instead restore this amount. +#define SPELL_MP_COST 10 + +///The player is currently in the Shop. +#define UI_PANEL_SHOP "Shop" +///The player is currently in the World Map. +#define UI_PANEL_WORLD_MAP "World Map" +///The player is currently in Batle. +#define UI_PANEL_BATTLE "Battle" +///The player is currently between battles. +#define UI_PANEL_BETWEEN_FIGHTS "Between Battle" +///The player is currently Game Overed. +#define UI_PANEL_GAMEOVER "Game Over" + +///The player is set to counterattack the enemy's next move. +#define BATTLE_ATTACK_FLAG_COUNTERATTACK (1<<0) +///The player is set to defend against the enemy's next move. +#define BATTLE_ATTACK_FLAG_DEFEND (1<<1) + +///The player is trying to Attack the Enemy. +#define BATTLE_ARCADE_PLAYER_ATTACK "Attack" +///The player is trying to Attack the Enemy with an MP boost. +#define BATTLE_ARCADE_PLAYER_HEAVY_ATTACK "Heavy Attack" +///The player is setting themselves to counterattack a potential incoming Enemy attack. +#define BATTLE_ARCADE_PLAYER_COUNTERATTACK "Counterattack" +///The player is defending against the Enemy and restoring MP. +#define BATTLE_ARCADE_PLAYER_DEFEND "Defend" + +/obj/machinery/computer/arcade/battle + name = "battle arcade" + desc = "Explore vast worlds and conquer." + icon_state = "arcade" + icon_screen = "fighters" + circuit = /obj/item/circuitboard/computer/arcade/battle + + ///List of all battle arcade gear that is available in the shop in game. + var/static/list/battle_arcade_gear_list + ///List of all worlds in the game. + var/static/list/all_worlds = list( + BATTLE_WORLD_ONE = 1, + BATTLE_WORLD_TWO = 1.25, + BATTLE_WORLD_THREE = 1.5, + BATTLE_WORLD_FOUR = 1.75, + BATTLE_WORLD_FIVE = 2, + BATTLE_WORLD_SIX = 2.25, + BATTLE_WORLD_SEVEN = 2.5, + BATTLE_WORLD_EIGHT = 2.75, + BATTLE_WORLD_NINE = 3, + ) + var/static/list/all_attack_types = list( + BATTLE_ARCADE_PLAYER_ATTACK = "Attack the enemy in a default attack at no MP cost.", + BATTLE_ARCADE_PLAYER_HEAVY_ATTACK = "Attack the enemy with the power of Magic, costing MP for additional damage.", + BATTLE_ARCADE_PLAYER_COUNTERATTACK = "Use magic to prepare a counterattack of your enemy, allowing you to deal extra damage if you succeed.", + BATTLE_ARCADE_PLAYER_DEFEND = "Defend from the next incoming attack, lowing the amount of damage you take while restoring some HP and MP.", + ) + ///The world we're currently in. + var/player_current_world = BATTLE_WORLD_ONE + ///The latest world the player has unlocked, granting access to all worlds below this. + var/latest_unlocked_world = BATTLE_WORLD_ONE + ///How many enemies we've defeated in a row, used to tell when we need to spawn the boss in. + var/enemies_defeated + ///The current panel the player is viewieng in the UI. + var/ui_panel = UI_PANEL_WORLD_MAP + + /** PLAYER INFORMATION */ + + ///Boolean on whether it's the player's time to do their turn. + var/player_turn = TRUE + ///How much money the player has, used in the Inn. Starts with the default price for a single item. + var/player_gold = DEFAULT_ITEM_PRICE + ///The current amount of HP the player has. + var/player_current_hp = PLAYER_MAX_HP + ///The current amount of MP the player has. + var/player_current_mp = PLAYER_MAX_MP + ///Assoc list of gear the player has equipped. + var/list/datum/battle_arcade_gear/equipped_gear = list( + WEAPON_SLOT = null, + ARMOR_SLOT = null, + ) + + /** CURRENT ENEMY INFORMATION */ + + ///A feedback message displayed in the UI during combat sequences. + var/feedback_message + ///Determines which boss image to use on the UI. + var/enemy_icon_id = 1 + ///The enemy's name + var/enemy_name + ///How much HP the current enemy has. + var/enemy_max_hp + ///How much HP the current enemy has. + var/enemy_hp + ///How much MP the current enemy has. + var/enemy_mp + ///How much gold the enemy will drop, randomized on new opponent. + var/enemy_gold_reward + ///unique to the emag mode, acts as a time limit where the player dies when it reaches 0. + var/bomb_cooldown = 19 + +/obj/machinery/computer/arcade/battle/Initialize(mapload, obj/item/circuitboard/C) + . = ..() + if(isnull(battle_arcade_gear_list)) + var/list/all_gear = list() + for(var/datum/battle_arcade_gear/template as anything in subtypesof(/datum/battle_arcade_gear)) + if(!(template::slot)) //needs to fit in something. + continue + all_gear[template::name] = new template + battle_arcade_gear_list = all_gear + +/obj/machinery/computer/arcade/battle/emag_act(mob/user, obj/item/card/emag/emag_card) + if(obj_flags & EMAGGED) + return FALSE + obj_flags |= EMAGGED + balloon_alert(user, "hard mode enabled") + to_chat(user, span_warning("A mesmerizing Rhumba beat starts playing from the arcade machine's speakers!")) + setup_new_opponent() + feedback_message = "If you die in the game, you die for real!" + SStgui.update_uis(src) + return TRUE + +/obj/machinery/computer/arcade/battle/reset_cabinet(mob/living/user) + enemy_name = null + player_turn = initial(player_turn) + feedback_message = initial(feedback_message) + player_current_world = initial(player_current_world) + latest_unlocked_world = initial(latest_unlocked_world) + enemies_defeated = initial(enemies_defeated) + player_gold = initial(player_gold) + player_current_hp = initial(player_current_hp) + player_current_mp = initial(player_current_mp) + ui_panel = initial(ui_panel) + bomb_cooldown = initial(bomb_cooldown) + equipped_gear = list(WEAPON_SLOT = null, ARMOR_SLOT = null) + return ..() + +///Sets up a new opponent depending on what stage they are at. +/obj/machinery/computer/arcade/battle/proc/setup_new_opponent(enemy_gets_first_move = FALSE) + var/name_adjective + var/new_name + + if(check_holidays(HALLOWEEN)) + name_adjective = pick_list(ARCADE_FILE, "rpg_adjective_halloween") + new_name = pick_list(ARCADE_FILE, "rpg_enemy_halloween") + else if(check_holidays(CHRISTMAS)) + name_adjective = pick_list(ARCADE_FILE, "rpg_adjective_xmas") + new_name = pick_list(ARCADE_FILE, "rpg_enemy_xmas") + else if(check_holidays(VALENTINES)) + name_adjective = pick_list(ARCADE_FILE, "rpg_adjective_valentines") + new_name = pick_list(ARCADE_FILE, "rpg_enemy_valentines") + else + name_adjective = pick_list(ARCADE_FILE, "rpg_adjective") + new_name = pick_list(ARCADE_FILE, "rpg_enemy") + + enemy_hp = round(rand(90, 125) * all_worlds[player_current_world], 1) + enemy_mp = round(rand(20, 30) * all_worlds[player_current_world], 1) + enemy_gold_reward = rand((DEFAULT_ITEM_PRICE / 2), DEFAULT_ITEM_PRICE) + + // there's only one boss in each stage (except the last) + if((player_current_world == latest_unlocked_world) && enemies_defeated == WORLD_ENEMY_BOSS) + enemy_mp *= 1.25 + enemy_hp *= 1.25 + enemy_gold_reward *= 1.5 + name_adjective = "Big Boss" + + enemy_icon_id = rand(1,6) + enemy_name = "The [name_adjective] [new_name]" + feedback_message = "New game started against [enemy_name]" + + if(obj_flags & EMAGGED) + enemy_name = "Cuban Pete" + enemy_hp += 100 //extra HP just to make cuban pete even more bullshit + + //set max HP to reference later + enemy_max_hp = enemy_hp + //set the player to fight now. + ui_panel = UI_PANEL_BATTLE + + if(enemy_gets_first_move) + perform_enemy_turn() + +/** + * on_battle_win + * + * Called when the player wins a level, this handles giving EXP, loot, tickets, etc. + * It also handles clearing the enemy out for the next one, and unlocking new worlds. + * We stop at BATTLE_WORLD_NINE because it is the last stage, and has infinite bosses. + */ +/obj/machinery/computer/arcade/battle/proc/on_battle_win(mob/user) + enemy_name = null + feedback_message = null + player_turn = TRUE + if(player_current_world == latest_unlocked_world) + if(enemies_defeated == WORLD_ENEMY_BOSS) + enemies_defeated = 0 + //the last stage doesn't have a next one to move onto. + if(latest_unlocked_world != BATTLE_WORLD_NINE) + var/current_world = all_worlds.Find(latest_unlocked_world) + latest_unlocked_world = all_worlds[current_world + 1] + ui_panel = UI_PANEL_WORLD_MAP + say("New world unlocked, [latest_unlocked_world]!") + enemies_defeated++ + if(obj_flags & EMAGGED) + obj_flags &= ~EMAGGED + bomb_cooldown = initial(bomb_cooldown) + new /obj/effect/spawner/newbomb/plasma(loc, /obj/item/assembly/timer) + new /obj/item/clothing/head/collectable/petehat(loc) + message_admins("[ADMIN_LOOKUPFLW(usr)] has outbombed Cuban Pete and been awarded a bomb.") + usr.log_message("outbombed Cuban Pete and has been awarded a bomb.", LOG_GAME) + else + visible_message(span_notice("[src] dispenses 2 tickets!")) + new /obj/item/stack/arcadeticket((get_turf(src)), 2) + player_gold += enemy_gold_reward + if(user) + var/exp_gained = DEFAULT_EXP_GAIN * all_worlds[player_current_world] + user.mind?.adjust_experience(/datum/skill/gaming, exp_gained) + user.won_game() + SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("win", (obj_flags & EMAGGED ? "emagged":"normal"))) + playsound(loc, 'sound/arcade/win.ogg', 40) + if(ui_panel != UI_PANEL_WORLD_MAP) //we havent been booted to world map, we're still going. + ui_panel = UI_PANEL_BETWEEN_FIGHTS + +///Called when a mob loses at the battle arcade. +/obj/machinery/computer/arcade/battle/proc/lose_game(mob/user) + if(obj_flags & EMAGGED) + var/mob/living/living_user = user + if(istype(living_user)) + living_user.investigate_log("has been gibbed by an emagged Orion Trail game.", INVESTIGATE_DEATHS) + living_user.gib(DROP_ALL_REMAINS) + user.lost_game() + SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "hp", (obj_flags & EMAGGED ? "emagged":"normal"))) + SStgui.update_uis(src) + +///Called when the enemy attacks you. +/obj/machinery/computer/arcade/battle/proc/user_take_damage(mob/user, base_damage_taken) + var/datum/battle_arcade_gear/armor = equipped_gear[ARMOR_SLOT] + var/damage_taken = (base_damage_taken * all_worlds[player_current_world]) / (!isnull(armor) ? armor.bonus_modifier : 1) + player_current_hp -= round(max(0, damage_taken), 1) + if(player_current_hp <= 0) + ui_panel = UI_PANEL_GAMEOVER + feedback_message = "GAME OVER." + say("You have been crushed! GAME OVER.") + playsound(loc, 'sound/arcade/lose.ogg', 40, TRUE) + lose_game(user) + else + feedback_message = "User took [damage_taken] damage!" + playsound(loc, 'sound/arcade/hit.ogg', 40, TRUE, extrarange = -3) + SStgui.update_uis(src) + +///Called when you attack the enemy. +/obj/machinery/computer/arcade/battle/proc/process_player_attack(mob/user, attack_type) + var/damage_dealt + switch(attack_type) + if(BATTLE_ARCADE_PLAYER_ATTACK) + var/datum/battle_arcade_gear/weapon = equipped_gear[WEAPON_SLOT] + damage_dealt = (rand(5, 15) * (!isnull(weapon) ? weapon.bonus_modifier : 1)) + if(BATTLE_ARCADE_PLAYER_HEAVY_ATTACK) + var/datum/battle_arcade_gear/weapon = equipped_gear[WEAPON_SLOT] + damage_dealt = (rand(15, 25) * (!isnull(weapon) ? weapon.bonus_modifier : 1)) + if(BATTLE_ARCADE_PLAYER_COUNTERATTACK) + feedback_message = "User prepares to counterattack!" + process_enemy_turn(user, defending_flags = BATTLE_ATTACK_FLAG_COUNTERATTACK) + playsound(loc, 'sound/arcade/mana.ogg', 40, TRUE, extrarange = -3) + if(BATTLE_ARCADE_PLAYER_DEFEND) + feedback_message = "User pulls up their shield!" + process_enemy_turn(user, defending_flags = BATTLE_ATTACK_FLAG_DEFEND) + playsound(loc, 'sound/arcade/mana.ogg', 40, TRUE, extrarange = -3) + + if(!damage_dealt) + return + enemy_hp -= round(max(0, damage_dealt), 1) + feedback_message = "[enemy_name] took [damage_dealt] damage!" + playsound(loc, 'sound/arcade/hit.ogg', 40, TRUE, extrarange = -3) + process_enemy_turn(user) + +///Called when you successfully counterattack the enemy. +/obj/machinery/computer/arcade/battle/proc/successful_counterattack(mob/user) + var/datum/battle_arcade_gear/weapon = equipped_gear[WEAPON_SLOT] + var/damage_dealt = (rand(20, 30) * (!isnull(weapon) ? weapon.bonus_modifier : 1)) + enemy_hp -= round(max(0, damage_dealt), 1) + feedback_message = "User counterattacked for [damage_dealt] damage!" + playsound(loc, 'sound/arcade/boom.ogg', 40, TRUE, extrarange = -3) + if(enemy_hp <= 0) + on_battle_win(user) + SStgui.update_uis(src) + +///Handles the delay between the user's and enemy's turns to process what's going on. +/obj/machinery/computer/arcade/battle/proc/process_enemy_turn(mob/user, defending_flags = NONE) + if(enemy_hp <= 0) + return on_battle_win(user) + //if emagged, cuban pete will set up a bomb acting up as a timer. when it reaches 0 the player fucking dies + + if(obj_flags & EMAGGED) + bomb_cooldown-- + switch(bomb_cooldown) + if(18) + feedback_message = "[enemy_name] takes two valve tank and links them together, what's he planning?" + if(15) + feedback_message = "[enemy_name] adds a remote control to the tan- ho god is that a bomb?" + if(12) + feedback_message = "[enemy_name] throws the bomb next to you, you'r too scared to pick it up." + if(6) + feedback_message = "[enemy_name]'s hand brushes the remote linked to the bomb, your heart skipped a beat." + if(2) + feedback_message = "[enemy_name] is going to press the button! It's now or never!" + if(0) + player_current_hp = 0 //instant death + addtimer(CALLBACK(src, PROC_REF(perform_enemy_turn), user, defending_flags), 1 SECONDS) + +/** + * perform_enemy_turn + * + * Actually performs the enemy's turn. + * We first roll to see if the enemy should use magic. As their HP goes lower, the chances of self healing goes higher, but + * if they lack the MP, then it's rolling to steal MP from the player. + * After, we will roll to see if the player counterattacks the enemy (if set), otherwise we will attack normally. + */ +/obj/machinery/computer/arcade/battle/proc/perform_enemy_turn(mob/user, defending_flags = NONE) + player_turn = TRUE + var/chance_to_magic = round(max((-(enemy_hp - enemy_max_hp) / 2), 75), 1) + if((enemy_hp != enemy_max_hp) && prob(chance_to_magic)) + if(enemy_mp >= 10) + var/healed_amount = rand(10, 20) + enemy_hp = round(min(enemy_max_hp, enemy_hp + healed_amount), 1) + enemy_mp -= round(max(0, 10), 1) + feedback_message = "[enemy_name] healed for [healed_amount] health points!" + playsound(loc, 'sound/arcade/heal.ogg', 40, TRUE, extrarange = -3) + SStgui.update_uis(src) + return + if(player_current_mp >= 5) //minimum to steal + var/healed_amount = rand(5, 10) + player_current_mp -= round(max(0, healed_amount), 1) + enemy_mp += healed_amount + feedback_message = "[enemy_name] stole [healed_amount] MP from you!" + playsound(loc, 'sound/arcade/steal.ogg', 40, TRUE) + SStgui.update_uis(src) + return + //we couldn't heal ourselves or steal MP, we'll just attack instead. + var/skill_level = user?.mind?.get_skill_level(/datum/skill/gaming) || 1 + var/chance_at_counterattack = 40 + (skill_level * 5) //at level 1 this is 45, at legendary this is 75 + var/damage_dealt = (defending_flags & BATTLE_ATTACK_FLAG_DEFEND) ? rand(5, 10) : rand(15, 20) + if((defending_flags & BATTLE_ATTACK_FLAG_COUNTERATTACK) && prob(chance_at_counterattack)) + return successful_counterattack(user) + return user_take_damage(user, damage_dealt) + +/obj/machinery/computer/arcade/battle/ui_data(mob/user) + var/list/data = ..() + + data["feedback_message"] = feedback_message + data["shop_items"] = list() + for(var/gear_name in battle_arcade_gear_list) + var/datum/battle_arcade_gear/gear = battle_arcade_gear_list[gear_name] + if(latest_unlocked_world != gear.world_available) + continue + data["shop_items"] += list(gear_name) + data["ui_panel"] = ui_panel + data["player_current_world"] = player_current_world + data["unlocked_world_modifier"] = all_worlds[latest_unlocked_world] + data["latest_unlocked_world_position"] = all_worlds.Find(latest_unlocked_world) + data["player_gold"] = player_gold + data["player_current_hp"] = player_current_hp + data["player_current_mp"] = player_current_mp + data["enemy_icon_id"] = "boss[enemy_icon_id].gif" + data["enemy_name"] = enemy_name + data["enemy_max_hp"] = enemy_max_hp + data["enemy_hp"] = enemy_hp + data["enemy_mp"] = enemy_mp + + data["equipped_gear"] = list() + for(var/gear_slot as anything in equipped_gear) + var/datum/battle_arcade_gear/user_gear = equipped_gear[gear_slot] + if(!istype(user_gear)) + continue + data["equipped_gear"] += list(list( + "name" = user_gear.name, + "slot" = gear_slot, + )) + + return data + +/obj/machinery/computer/arcade/battle/ui_static_data(mob/user) + var/list/data = ..() + + data["all_worlds"] = list() + for(var/individual_world in all_worlds) + UNTYPED_LIST_ADD(data["all_worlds"], individual_world) + data["attack_types"] = list() + for(var/individual_attack_type in all_attack_types) + UNTYPED_LIST_ADD(data["attack_types"], list("name" = individual_attack_type, "tooltip" = all_attack_types[individual_attack_type])) + data["cost_of_items"] = DEFAULT_ITEM_PRICE + data["max_hp"] = PLAYER_MAX_HP + data["max_mp"] = PLAYER_MAX_MP + + return data + +/obj/machinery/computer/arcade/battle/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/simple/arcade), + ) + +/obj/machinery/computer/arcade/battle/ui_interact(mob/user, datum/tgui/ui) + . = ..() + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "BattleArcade", "Battle Arcade") + ui.set_autoupdate(FALSE) + ui.open() + +/obj/machinery/computer/arcade/battle/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + var/mob/living/gamer = ui.user + if(!istype(gamer)) + return + + switch(ui_panel) + if(UI_PANEL_GAMEOVER) + switch(action) + if("restart") + reset_cabinet() + return TRUE + if(UI_PANEL_SHOP) + switch(action) + if("sleep") + if(player_gold < DEFAULT_ITEM_PRICE / 2) + say("You don't have enough gold to rest!") + return TRUE + player_gold -= DEFAULT_ITEM_PRICE / 2 + playsound(loc, 'sound/mecha/skyfall_power_up.ogg', 40) + player_current_hp = PLAYER_MAX_HP + player_current_mp = PLAYER_MAX_MP + return TRUE + if("buy_item") + var/datum/battle_arcade_gear/gear = battle_arcade_gear_list[params["purchasing_item"]] + if(latest_unlocked_world != gear.world_available || equipped_gear[gear.slot] == gear) + say("That item is not in stock.") + return TRUE + if(player_gold < (DEFAULT_ITEM_PRICE * all_worlds[latest_unlocked_world])) + say("You don't have enough gold to buy that!") + return TRUE + player_gold -= DEFAULT_ITEM_PRICE * all_worlds[latest_unlocked_world] + equipped_gear[gear.slot] = gear + return TRUE + if("leave") + ui_panel = UI_PANEL_WORLD_MAP + return TRUE + if(UI_PANEL_WORLD_MAP) + switch(action) + if("start_fight") + var/world_travelling = all_worlds.Find(params["selected_arena"]) + var/max_unlocked_worlds = all_worlds.Find(latest_unlocked_world) + if(world_travelling > max_unlocked_worlds) + say("That world is not unlocked yet!") + return TRUE + player_current_world = all_worlds[world_travelling] + setup_new_opponent() + return TRUE + if("enter_inn") + ui_panel = UI_PANEL_SHOP + return TRUE + if(UI_PANEL_BETWEEN_FIGHTS) + switch(action) + if("continue_without_rest") + setup_new_opponent() + return TRUE + if("continue_with_rest") + if(prob(60)) + playsound(loc, 'sound/mecha/skyfall_power_up.ogg', 40) + player_current_hp = PLAYER_MAX_HP + player_current_mp = PLAYER_MAX_MP + else + playsound(loc, 'sound/machines/defib_zap.ogg', 40) + if(prob(40)) + //You got robbed, and now have to go to your next fight. + player_gold /= 2 + else + //You got ambushed, the enemy gets the first hit. + setup_new_opponent(enemy_gets_first_move = TRUE) + return TRUE + setup_new_opponent() + return TRUE + if("abandon_quest") + if(player_current_world == latest_unlocked_world) + enemies_defeated = 0 + ui_panel = UI_PANEL_WORLD_MAP + return TRUE + if(UI_PANEL_BATTLE) + if(!player_turn) + return TRUE + player_turn = FALSE + switch(action) + if(BATTLE_ARCADE_PLAYER_ATTACK) + process_player_attack(gamer, BATTLE_ARCADE_PLAYER_ATTACK) + return TRUE + if(BATTLE_ARCADE_PLAYER_HEAVY_ATTACK) + if(player_current_mp < SPELL_MP_COST) + say("You don't have enough MP to counterattack!") + player_turn = TRUE + return TRUE + player_current_mp -= SPELL_MP_COST + process_player_attack(gamer, BATTLE_ARCADE_PLAYER_HEAVY_ATTACK) + return TRUE + if(BATTLE_ARCADE_PLAYER_COUNTERATTACK) + if(player_current_mp < SPELL_MP_COST) + say("You don't have enough MP to counterattack!") + player_turn = TRUE + return TRUE + player_current_mp -= SPELL_MP_COST + process_player_attack(gamer, BATTLE_ARCADE_PLAYER_COUNTERATTACK) + return TRUE + if(BATTLE_ARCADE_PLAYER_DEFEND) + player_current_hp = round(min(player_current_hp + (SPELL_MP_COST / 2), PLAYER_MAX_HP), 1) + player_current_mp = round(min(player_current_mp + SPELL_MP_COST, PLAYER_MAX_MP), 1) + process_player_attack(gamer, BATTLE_ARCADE_PLAYER_DEFEND) + return TRUE + if("flee") + //you can't outrun the cuban pete + if(obj_flags & EMAGGED) + lose_game(gamer) + return + player_turn = TRUE + ui_panel = UI_PANEL_WORLD_MAP + player_gold /= 2 + return TRUE + //they pressed something but it wasn't in the menu, we'll be nice and give them back their turn anyway. + player_turn = TRUE + +#undef WORLD_ENEMY_BOSS +#undef DEFAULT_EXP_GAIN +#undef DEFAULT_ITEM_PRICE + +#undef PLAYER_MAX_HP +#undef PLAYER_MAX_MP +#undef SPELL_MP_COST + +#undef UI_PANEL_SHOP +#undef UI_PANEL_WORLD_MAP +#undef UI_PANEL_BATTLE +#undef UI_PANEL_BETWEEN_FIGHTS +#undef UI_PANEL_GAMEOVER + +#undef BATTLE_ATTACK_FLAG_COUNTERATTACK +#undef BATTLE_ATTACK_FLAG_DEFEND + +#undef BATTLE_ARCADE_PLAYER_ATTACK +#undef BATTLE_ARCADE_PLAYER_HEAVY_ATTACK +#undef BATTLE_ARCADE_PLAYER_COUNTERATTACK +#undef BATTLE_ARCADE_PLAYER_DEFEND diff --git a/code/game/machinery/computer/arcade/battle_gear.dm b/code/game/machinery/computer/arcade/battle_gear.dm new file mode 100644 index 00000000000..32d1d73dd4f --- /dev/null +++ b/code/game/machinery/computer/arcade/battle_gear.dm @@ -0,0 +1,126 @@ +/datum/battle_arcade_gear + ///The name of the gear, used in shops. + var/name = "Gear" + ///The slot this gear fits into + var/slot + ///The world the player has to be at in order to buy this item. + var/world_available + ///The stat given by the gear + var/bonus_modifier + +/datum/battle_arcade_gear/tier_1 + world_available = BATTLE_WORLD_ONE + +/datum/battle_arcade_gear/tier_1/weapon + name = "Sword" + slot = WEAPON_SLOT + bonus_modifier = 1.5 + +/datum/battle_arcade_gear/tier_1/armor + name = "Leather Armor" + slot = ARMOR_SLOT + bonus_modifier = 1.5 + +/datum/battle_arcade_gear/tier_2 + world_available = BATTLE_WORLD_TWO + +/datum/battle_arcade_gear/tier_2/weapon + name = "Axe" + slot = WEAPON_SLOT + bonus_modifier = 1.75 + +/datum/battle_arcade_gear/tier_2/armor + name = "Chainmail" + slot = ARMOR_SLOT + bonus_modifier = 1.75 + +/datum/battle_arcade_gear/tier_3 + world_available = BATTLE_WORLD_THREE + +/datum/battle_arcade_gear/tier_3/weapon + name = "Mace" + slot = WEAPON_SLOT + bonus_modifier = 2 + +/datum/battle_arcade_gear/tier_3/armor + name = "Plate Armor" + slot = ARMOR_SLOT + bonus_modifier = 2 + +/datum/battle_arcade_gear/tier_4 + world_available = BATTLE_WORLD_FOUR + +/datum/battle_arcade_gear/tier_4/weapon + name = "Greatsword" + slot = WEAPON_SLOT + bonus_modifier = 2.5 + +/datum/battle_arcade_gear/tier_4/armor + name = "Full Plate Armor" + slot = ARMOR_SLOT + bonus_modifier = 2.5 + +/datum/battle_arcade_gear/tier_5 + world_available = BATTLE_WORLD_FIVE + +/datum/battle_arcade_gear/tier_5/weapon + name = "Halberd" + slot = WEAPON_SLOT + bonus_modifier = 3 + +/datum/battle_arcade_gear/tier_5/armor + name = "Dragon Scale Armor" + slot = ARMOR_SLOT + bonus_modifier = 3 + +/datum/battle_arcade_gear/tier_6 + world_available = BATTLE_WORLD_SIX + +/datum/battle_arcade_gear/tier_6/weapon + name = "Warhammer" + slot = WEAPON_SLOT + bonus_modifier = 3.5 + +/datum/battle_arcade_gear/tier_6/armor + name = "Adamantine Armor" + slot = ARMOR_SLOT + bonus_modifier = 3.5 + +/datum/battle_arcade_gear/tier_7 + world_available = BATTLE_WORLD_SEVEN + +/datum/battle_arcade_gear/tier_7/weapon + name = "Excalibur" + slot = WEAPON_SLOT + bonus_modifier = 4 + +/datum/battle_arcade_gear/tier_7/armor + name = "Ethereal Armor" + slot = ARMOR_SLOT + bonus_modifier = 4 + +/datum/battle_arcade_gear/tier_8 + world_available = BATTLE_WORLD_EIGHT + +/datum/battle_arcade_gear/tier_8/weapon + name = "Gungnir" + slot = WEAPON_SLOT + bonus_modifier = 4.5 + +/datum/battle_arcade_gear/tier_8/armor + name = "Celestial Armor" + slot = ARMOR_SLOT + bonus_modifier = 4.5 + +/datum/battle_arcade_gear/tier_9 + world_available = BATTLE_WORLD_NINE + +/datum/battle_arcade_gear/tier_9/weapon + name = "Mjolnir" + slot = WEAPON_SLOT + bonus_modifier = 5 + +/datum/battle_arcade_gear/tier_9/armor + name = "Void Armor" + slot = ARMOR_SLOT + bonus_modifier = 5 diff --git a/code/game/machinery/computer/arcade/orion.dm b/code/game/machinery/computer/arcade/orion.dm index 945cbb5593a..85bebddd25c 100644 --- a/code/game/machinery/computer/arcade/orion.dm +++ b/code/game/machinery/computer/arcade/orion.dm @@ -1,23 +1,13 @@ -// *** THE ORION TRAIL ** // - #define ORION_TRAIL_WINTURN 9 -//defines in machines.dm - -///assoc list, [datum singleton] = weight -GLOBAL_LIST_INIT(orion_events, generate_orion_events()) - -/proc/generate_orion_events() - . = list() - for(var/path in subtypesof(/datum/orion_event)) - var/datum/orion_event/new_event = new path(src) - .[new_event] = new_event.weight - /obj/machinery/computer/arcade/orion_trail name = "The Orion Trail" desc = "Learn how our ancestors got to Orion, and have fun in the process!" icon_state = "arcade" circuit = /obj/item/circuitboard/computer/arcade/orion_trail + + ///List of all orion events, created on Initialize. + var/static/list/orion_events var/busy = FALSE //prevent clickspam that allowed people to ~speedrun~ the game. var/engine = 0 var/hull = 0 @@ -44,12 +34,18 @@ GLOBAL_LIST_INIT(orion_events, generate_orion_events()) /obj/machinery/computer/arcade/orion_trail/Initialize(mapload) . = ..() + if(isnull(orion_events)) + var/list/events = list() + for(var/path in subtypesof(/datum/orion_event)) + var/datum/orion_event/new_event = new path(src) + events[new_event] = new_event.weight + orion_events = events radio = new /obj/item/radio(src) radio.set_listening(FALSE) setup_events() /obj/machinery/computer/arcade/orion_trail/proc/setup_events() - events = GLOB.orion_events + events = orion_events.Copy() /obj/machinery/computer/arcade/orion_trail/Destroy() QDEL_NULL(radio) @@ -81,7 +77,7 @@ GLOBAL_LIST_INIT(orion_events, generate_orion_events()) settlers = list("Kirk","Worf","Gene") /obj/machinery/computer/arcade/orion_trail/kobayashi/setup_events() - events = GLOB.orion_events.Copy() + events = orion_events.Copy() for(var/datum/orion_event/event as anything in events) if(!(event.type in event_whitelist)) events.Remove(event) @@ -196,8 +192,6 @@ GLOBAL_LIST_INIT(orion_events, generate_orion_events()) . = TRUE - - var/gamer_skill_level = 0 var/gamer_skill = 0 var/gamer_skill_rands = 0 @@ -316,7 +310,6 @@ GLOBAL_LIST_INIT(orion_events, generate_orion_events()) if(food > ORION_TRADE_RATE) fuel += ORION_TRADE_RATE food -= ORION_TRADE_RATE - add_fingerprint(gamer) /** * pickweights a new event, sets event var as it. it then preps the event if it needs it @@ -502,62 +495,56 @@ GLOBAL_LIST_INIT(orion_events, generate_orion_events()) obj_flags |= EMAGGED return TRUE -/mob/living/basic/trooper/syndicate/ranged/smg/orion - name = "spaceport security" - desc = "Premier corporate security forces for all spaceports found along the Orion Trail." - faction = list(FACTION_ORION) - loot = list() - +///A minibomb achieved from winning at emagged Orion. /obj/item/orion_ship name = "model settler ship" desc = "A model spaceship, it looks like those used back in the day when travelling to Orion! It even has a miniature FX-293 reactor, which was renowned for its instability and tendency to explode..." icon = 'icons/obj/toys/toy.dmi' icon_state = "ship" w_class = WEIGHT_CLASS_SMALL - var/active = 0 //if the ship is on + ///Boolean on whether the ship is active, setting itself off for destruction. + var/active = 0 /obj/item/orion_ship/examine(mob/user) . = ..() if(!(in_range(user, src))) return - if(!active) - . += span_notice("There's a little switch on the bottom. It's flipped down.") - else + if(active) . += span_notice("There's a little switch on the bottom. It's flipped up.") + return + . += span_notice("There's a little switch on the bottom. It's flipped down.") -/obj/item/orion_ship/attack_self(mob/user) //Minibomb-level explosion. Should probably be more because of how hard it is to survive the machine! Also, just over a 5-second fuse +/obj/item/orion_ship/attack_self(mob/user) if(active) return log_bomber(usr, "primed an explosive", src, "for detonation") - to_chat(user, span_warning("You flip the switch on the underside of [src].")) - active = 1 - visible_message(span_notice("[src] softly beeps and whirs to life!")) - playsound(loc, 'sound/machines/defib_SaftyOn.ogg', 25, TRUE) - say("This is ship ID #[rand(1,1000)] to Orion Port Authority. We're coming in for landing, over.") - sleep(2 SECONDS) - visible_message(span_warning("[src] begins to vibrate...")) - say("Uh, Port? Having some issues with our reactor, could you check it out? Over.") - sleep(3 SECONDS) - say("Oh, God! Code Eight! CODE EIGHT! IT'S GONNA BL-") - playsound(loc, 'sound/machines/buzz-sigh.ogg', 25, TRUE) - sleep(0.36 SECONDS) - visible_message(span_userdanger("[src] explodes!")) - explosion(src, devastation_range = 2, heavy_impact_range = 4, light_impact_range = 8, flame_range = 16) - qdel(src) + active = TRUE + addtimer(CALLBACK(src, PROC_REF(commit_explosion)), 1 SECONDS) -/obj/singularity/orion - move_self = FALSE +///After some dialogue (which doubles as the timer until explosion), causes a minibomb-level explosion. +/obj/item/orion_ship/proc/commit_explosion(dialogue_level = 0) + var/time_for_next_level + switch(dialogue_level) + if(0) + say("This is ship ID #[rand(1,1000)] to Orion Port Authority. We're coming in for landing, over.") + time_for_next_level = 2 SECONDS + if(1) + say("Uh, Port? Having some issues with our reactor, could you check it out? Over.") + time_for_next_level = 3 SECONDS + if(2) + say("Oh, God! Code Eight! CODE EIGHT! IT'S GONNA BL-") + playsound(loc, 'sound/machines/buzz-sigh.ogg', 25, TRUE) + time_for_next_level = 0.36 SECONDS + if(3 to INFINITY) + visible_message(span_userdanger("[src] explodes!")) + explosion(src, devastation_range = 2, heavy_impact_range = 4, light_impact_range = 8, flame_range = 16) + qdel(src) + return -/obj/singularity/orion/Initialize(mapload) - . = ..() - - var/datum/component/singularity/singularity = singularity_component.resolve() - singularity?.grav_pull = 1 - -/obj/singularity/orion/process(seconds_per_tick) - if(SPT_PROB(0.5, seconds_per_tick)) - mezzer() + if(time_for_next_level) + dialogue_level++ + addtimer(CALLBACK(src, PROC_REF(commit_explosion), dialogue_level), time_for_next_level) #undef ORION_TRAIL_WINTURN diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index 18ca1665765..750a1d5d53e 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -146,7 +146,7 @@ return FALSE -/obj/structure/frame/computer/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) +/obj/structure/frame/computer/item_interaction(mob/living/user, obj/item/tool, list/modifiers) . = ..() if(. & ITEM_INTERACT_ANY_BLOCKER) return . diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index b244cba4aa6..5b27bfabf70 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -30,7 +30,7 @@ // Convert networks to lowercase for(var/i in network) network -= i - network += lowertext(i) + network += LOWER_TEXT(i) // Initialize map objects cam_screen = new cam_screen.generate_view(map_name) diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index a271517b0c4..1868bc3c38c 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -4,6 +4,8 @@ icon_screen = "cameras" icon_keyboard = "security_key" light_color = COLOR_SOFT_RED + processing_flags = START_PROCESSING_MANUALLY + var/list/z_lock = list() // Lock use to these z levels var/lock_override = NONE var/mob/camera/ai_eye/remote/eyeobj @@ -30,7 +32,7 @@ . = ..() for(var/i in networks) networks -= i - networks += lowertext(i) + networks += LOWER_TEXT(i) if(lock_override) if(lock_override & CAMERA_LOCK_STATION) z_lock |= SSmapping.levels_by_trait(ZTRAIT_STATION) @@ -50,6 +52,20 @@ if(move_down_action) actions += new move_down_action(src) +/obj/machinery/computer/camera_advanced/Destroy() + if(!QDELETED(current_user)) + unset_machine(current_user) + if(eyeobj) + QDEL_NULL(eyeobj) + QDEL_LIST(actions) + current_user = null + return ..() + +/obj/machinery/computer/camera_advanced/process() + if(!can_use(current_user) || (issilicon(current_user) && !current_user.has_unlimited_silicon_privilege)) + unset_machine(current_user) + return PROCESS_KILL + /obj/machinery/computer/camera_advanced/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock) for(var/i in networks) networks -= i @@ -73,6 +89,20 @@ /obj/machinery/proc/remove_eye_control(mob/living/user) CRASH("[type] does not implement ai eye handling") +/obj/machinery/computer/camera_advanced/proc/give_eye_control(mob/user) + if(isnull(user?.client)) + return + GrantActions(user) + current_user = user + eyeobj.eye_user = user + eyeobj.name = "Camera Eye ([user.name])" + user.remote_control = eyeobj + user.reset_perspective(eyeobj) + eyeobj.setLoc(eyeobj.loc) + if(should_supress_view_changes) + user.client.view_size.supress() + begin_processing() + /obj/machinery/computer/camera_advanced/remove_eye_control(mob/living/user) if(isnull(user?.client)) return @@ -90,23 +120,16 @@ eyeobj.eye_user = null user.remote_control = null current_user = null - unset_machine(user) playsound(src, 'sound/machines/terminal_off.ogg', 25, FALSE) -/obj/machinery/computer/camera_advanced/check_eye(mob/user) - if(!can_use(user) || (issilicon(user) && !user.has_unlimited_silicon_privilege)) - unset_machine(user) - -/obj/machinery/computer/camera_advanced/Destroy() - if(eyeobj) - QDEL_NULL(eyeobj) - QDEL_LIST(actions) - current_user = null - return ..() +/obj/machinery/computer/camera_advanced/on_set_is_operational(old_value) + if(!is_operational) + unset_machine(current_user) /obj/machinery/computer/camera_advanced/proc/unset_machine(mob/M) if(M == current_user) remove_eye_control(M) + end_processing() /obj/machinery/computer/camera_advanced/proc/can_use(mob/living/user) return can_interact(user) @@ -167,19 +190,6 @@ /obj/machinery/computer/camera_advanced/attack_ai(mob/user) return //AIs would need to disable their own camera procs to use the console safely. Bugs happen otherwise. -/obj/machinery/computer/camera_advanced/proc/give_eye_control(mob/user) - if(isnull(user?.client)) - return - GrantActions(user) - current_user = user - eyeobj.eye_user = user - eyeobj.name = "Camera Eye ([user.name])" - user.remote_control = eyeobj - user.reset_perspective(eyeobj) - eyeobj.setLoc(eyeobj.loc) - if(should_supress_view_changes) - user.client.view_size.supress() - /mob/camera/ai_eye/remote name = "Inactive Camera Eye" ai_detector_visible = FALSE diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index f9e06ab58b3..4c210e8fd26 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -54,7 +54,7 @@ icon_keyboard = "med_key" density = TRUE circuit = /obj/item/circuitboard/computer/scan_consolenew - + interaction_flags_click = ALLOW_SILICON_REACH light_color = LIGHT_COLOR_BLUE /// Link to the techweb's stored research. Used to retrieve stored mutations @@ -210,15 +210,9 @@ stored_research = tool.buffer return TRUE -/obj/machinery/computer/scan_consolenew/AltClick(mob/user) - // Make sure the user can interact with the machine. - . = ..() - if(!can_interact(user)) - return - if(!user.can_perform_action(src, ALLOW_SILICON_REACH)) - return - +/obj/machinery/computer/scan_consolenew/click_alt(mob/user) eject_disk(user) + return CLICK_ACTION_SUCCESS /obj/machinery/computer/scan_consolenew/Initialize(mapload) . = ..() @@ -235,7 +229,7 @@ // Set the default tgui state set_default_state() -/obj/machinery/computer/scan_consolenew/LateInitialize() +/obj/machinery/computer/scan_consolenew/post_machine_initialize() . = ..() // Link machine with research techweb. Used for discovering and accessing // already discovered mutations diff --git a/code/game/machinery/computer/mechlaunchpad.dm b/code/game/machinery/computer/mechlaunchpad.dm index 106f87f1788..7b80b6e95c8 100644 --- a/code/game/machinery/computer/mechlaunchpad.dm +++ b/code/game/machinery/computer/mechlaunchpad.dm @@ -34,7 +34,8 @@ SIGNAL_HANDLER connected_mechpad = null -/obj/machinery/computer/mechpad/LateInitialize() +/obj/machinery/computer/mechpad/post_machine_initialize() + . = ..() for(var/obj/machinery/mechpad/pad as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/mechpad)) if(pad == connected_mechpad) continue diff --git a/code/game/machinery/computer/operating_computer.dm b/code/game/machinery/computer/operating_computer.dm index bb809af0eea..d0ea49df27b 100644 --- a/code/game/machinery/computer/operating_computer.dm +++ b/code/game/machinery/computer/operating_computer.dm @@ -20,7 +20,7 @@ find_table() return INITIALIZE_HINT_LATELOAD -/obj/machinery/computer/operating/LateInitialize() +/obj/machinery/computer/operating/post_machine_initialize() . = ..() if(!CONFIG_GET(flag/no_default_techweb_link) && !linked_techweb) CONNECT_TO_RND_SERVER_ROUNDSTART(linked_techweb, src) diff --git a/code/game/machinery/computer/orders/order_items/mining/order_mining.dm b/code/game/machinery/computer/orders/order_items/mining/order_mining.dm index 686f8312671..0882c9ce99a 100644 --- a/code/game/machinery/computer/orders/order_items/mining/order_mining.dm +++ b/code/game/machinery/computer/orders/order_items/mining/order_mining.dm @@ -111,3 +111,7 @@ item_path = /obj/item/boulder_beacon desc = "A Bouldertech brand all-in-one boulder processing beacon. Each use will teleport in a component of a full boulder processing assembly line. Good for when you need to process additional boulders." cost_per_order = 875 + +/datum/orderable_item/mining/grapple_gun + item_path = /obj/item/grapple_gun + cost_per_order = 3000 diff --git a/code/game/machinery/computer/prisoner/_prisoner.dm b/code/game/machinery/computer/prisoner/_prisoner.dm index f1ce2555936..9777c1b209c 100644 --- a/code/game/machinery/computer/prisoner/_prisoner.dm +++ b/code/game/machinery/computer/prisoner/_prisoner.dm @@ -2,6 +2,7 @@ interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_REQUIRES_LITERACY /// ID card currently inserted into the computer. VAR_FINAL/obj/item/card/id/advanced/prisoner/contained_id + interaction_flags_click = ALLOW_SILICON_REACH /obj/machinery/computer/prisoner/on_deconstruction(disassembled) contained_id?.forceMove(drop_location()) @@ -20,10 +21,9 @@ if(contained_id) . += span_notice("Alt-click to eject the ID card.") -/obj/machinery/computer/prisoner/AltClick(mob/user) - . = ..() - if(user.can_perform_action(src, ALLOW_SILICON_REACH)) - id_eject(user) +/obj/machinery/computer/prisoner/click_alt(mob/user) + id_eject(user) + return CLICK_ACTION_SUCCESS /obj/machinery/computer/prisoner/proc/id_insert(mob/user, obj/item/card/id/advanced/prisoner/new_id) if(!istype(new_id)) diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm index 0915d4d1d17..5baf5497853 100644 --- a/code/game/machinery/computer/teleporter.dm +++ b/code/game/machinery/computer/teleporter.dm @@ -201,7 +201,7 @@ if (regime_set == "Teleporter") var/desc = tgui_input_list(usr, "Select a location to lock in", "Locking Computer", sort_list(targets)) - if(isnull(desc)) + if(isnull(desc) || !user.can_perform_action(src)) return set_teleport_target(targets[desc]) user.log_message("set the teleporter target to [targets[desc]].]", LOG_GAME) @@ -211,7 +211,7 @@ return var/desc = tgui_input_list(usr, "Select a station to lock in", "Locking Computer", sort_list(targets)) - if(isnull(desc)) + if(isnull(desc)|| !user.can_perform_action(src)) return var/obj/machinery/teleport/station/target_station = targets[desc] if(!target_station || !target_station.teleporter_hub) diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index f47948753ab..f0b3434ec85 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -107,15 +107,10 @@ return ITEM_INTERACT_BLOCKING return . -/obj/structure/frame/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) - . = ..() - if(. & ITEM_INTERACT_ANY_BLOCKER) - return . - +/obj/structure/frame/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(istype(tool, /obj/item/circuitboard)) // Install board will fail if passed an invalid circuitboard and give feedback return install_board(user, tool, by_hand = TRUE) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING - - return . + return NONE /** * Installs the passed circuit board into the frame diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm index 0a626459667..dea1972cea7 100644 --- a/code/game/machinery/dance_machine.dm +++ b/code/game/machinery/dance_machine.dm @@ -163,7 +163,6 @@ req_access = null anchored = TRUE resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION /obj/machinery/jukebox/disco/activate_music() . = ..() diff --git a/code/game/machinery/defibrillator_mount.dm b/code/game/machinery/defibrillator_mount.dm index c067fcfef0b..207a3f753ef 100644 --- a/code/game/machinery/defibrillator_mount.dm +++ b/code/game/machinery/defibrillator_mount.dm @@ -157,15 +157,13 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/defibrillator_mount, 28) to_chat(user, span_notice("You remove [src] from the wall.")) return TRUE -/obj/machinery/defibrillator_mount/AltClick(mob/living/carbon/user) - if(!istype(user) || !user.can_perform_action(src)) - return +/obj/machinery/defibrillator_mount/click_alt(mob/living/carbon/user) if(!defib) to_chat(user, span_warning("It'd be hard to remove a defib unit from a mount that has none.")) - return + return CLICK_ACTION_BLOCKING if(clamps_locked) to_chat(user, span_warning("You try to tug out [defib], but the mount's clamps are locked tight!")) - return + return CLICK_ACTION_BLOCKING if(!user.put_in_hands(defib)) to_chat(user, span_warning("You need a free hand!")) user.visible_message(span_notice("[user] unhooks [defib] from [src], dropping it on the floor."), \ @@ -174,6 +172,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/defibrillator_mount, 28) user.visible_message(span_notice("[user] unhooks [defib] from [src]."), \ span_notice("You slide out [defib] from [src] and unhook the charging cables.")) playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE) + return CLICK_ACTION_SUCCESS /obj/machinery/defibrillator_mount/charging name = "PENLITE defibrillator mount" diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index 61f12100de2..4f78fbf3a52 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -99,7 +99,7 @@ /obj/structure/barricade/wooden/crude name = "crude plank barricade" desc = "This space is blocked off by a crude assortment of planks." - icon_state = "woodenbarricade-old" + icon_state = "plankbarricade" drop_amount = 1 max_integrity = 50 proj_pass_rate = 65 @@ -107,7 +107,7 @@ /obj/structure/barricade/wooden/crude/snow desc = "This space is blocked off by a crude assortment of planks. It seems to be covered in a layer of snow." - icon_state = "woodenbarricade-snow-old" + icon_state = "plankbarricade_snow" max_integrity = 75 /obj/structure/barricade/wooden/make_debris() @@ -180,10 +180,9 @@ . = ..() . += span_notice("Alt-click to toggle modes.") -/obj/item/grenade/barrier/AltClick(mob/living/carbon/user) - if(!istype(user) || !user.can_perform_action(src)) - return +/obj/item/grenade/barrier/click_alt(mob/living/carbon/user) toggle_mode(user) + return CLICK_ACTION_SUCCESS /obj/item/grenade/barrier/proc/toggle_mode(mob/user) switch(mode) diff --git a/code/game/machinery/dish_drive.dm b/code/game/machinery/dish_drive.dm index 81961ce7187..fc74b18c03c 100644 --- a/code/game/machinery/dish_drive.dm +++ b/code/game/machinery/dish_drive.dm @@ -9,6 +9,7 @@ density = FALSE circuit = /obj/item/circuitboard/machine/dish_drive pass_flags = PASSTABLE + interaction_flags_click = ALLOW_SILICON_REACH /// List of dishes the drive can hold var/list/collectable_items = list(/obj/item/trash/waffles, // SKYRAT EDIT CHANGE - non-static list /obj/item/trash/waffles, @@ -143,9 +144,9 @@ balloon_alert(user, "disposal signal sent") do_the_dishes(TRUE) -/obj/machinery/dish_drive/AltClick(mob/living/user) - if(user.can_perform_action(src, ALLOW_SILICON_REACH)) - do_the_dishes(TRUE) +/obj/machinery/dish_drive/click_alt(mob/living/user) + do_the_dishes(TRUE) + return CLICK_ACTION_SUCCESS /obj/machinery/dish_drive/proc/do_the_dishes(manual) if(!LAZYLEN(dish_drive_contents)) diff --git a/code/game/machinery/dna_infuser/dna_infuser.dm b/code/game/machinery/dna_infuser/dna_infuser.dm index 8275eb1e948..6c239089f5d 100644 --- a/code/game/machinery/dna_infuser/dna_infuser.dm +++ b/code/game/machinery/dna_infuser/dna_infuser.dm @@ -288,17 +288,17 @@ return FALSE return TRUE -/obj/machinery/dna_infuser/AltClick(mob/user) - . = ..() +/obj/machinery/dna_infuser/click_alt(mob/user) if(infusing) balloon_alert(user, "not while it's on!") - return + return CLICK_ACTION_BLOCKING if(!infusing_from) balloon_alert(user, "no sample to eject!") - return + return CLICK_ACTION_BLOCKING balloon_alert(user, "ejected sample") infusing_from.forceMove(get_turf(src)) infusing_from = null + return CLICK_ACTION_SUCCESS #undef INFUSING_TIME #undef SCREAM_TIME diff --git a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm index f6e1e92c2a5..f19f3d725c7 100644 --- a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm @@ -103,7 +103,7 @@ /obj/item/organ/internal/tongue/rat/modify_speech(datum/source, list/speech_args) . = ..() - var/message = lowertext(speech_args[SPEECH_MESSAGE]) + var/message = LOWER_TEXT(speech_args[SPEECH_MESSAGE]) if(message == "hi" || message == "hi.") speech_args[SPEECH_MESSAGE] = "Cheesed to meet you!" if(message == "hi?") diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 917255e50b4..437acc60cdf 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1512,7 +1512,7 @@ /obj/machinery/door/airlock/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) if((damage_amount >= atom_integrity) && (damage_flag == BOMB)) - obj_flags |= NO_DECONSTRUCTION //If an explosive took us out, don't drop the assembly + obj_flags |= NO_DEBRIS_AFTER_DECONSTRUCTION //If an explosive took us out, don't drop the assembly . = ..() if(atom_integrity < (0.75 * max_integrity)) update_appearance() @@ -2169,7 +2169,7 @@ return ..() -/obj/machinery/door/airlock/external/LateInitialize() +/obj/machinery/door/airlock/external/post_machine_initialize() . = ..() if(space_dir) unres_sides |= space_dir diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index b63e94e6079..0ff933cc9b1 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -91,7 +91,7 @@ RegisterSignal(src, COMSIG_MACHINERY_POWER_LOST, PROC_REF(on_power_loss)) return INITIALIZE_HINT_LATELOAD -/obj/machinery/door/firedoor/LateInitialize() +/obj/machinery/door/firedoor/post_machine_initialize() . = ..() RegisterSignal(src, COMSIG_MERGER_ADDING, PROC_REF(merger_adding)) RegisterSignal(src, COMSIG_MERGER_REMOVING, PROC_REF(merger_removing)) diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 0849a5ad8c5..c69c865f6d1 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -66,11 +66,8 @@ /obj/machinery/door/window/Destroy() set_density(FALSE) - if(atom_integrity == 0) - playsound(src, SFX_SHATTER, 70, TRUE) electronics = null - var/turf/floor = get_turf(src) - floor.air_update_turf(TRUE, FALSE) + air_update_turf(TRUE, FALSE) return ..() /obj/machinery/door/window/update_icon_state() @@ -300,11 +297,12 @@ if(BURN) playsound(src, 'sound/items/welder.ogg', 100, TRUE) - /obj/machinery/door/window/on_deconstruction(disassembled) if(disassembled) return + playsound(src, SFX_SHATTER, 70, TRUE) + for(var/i in 1 to shards) drop_debris(new /obj/item/shard(src)) if(rods) diff --git a/code/game/machinery/embedded_controller/access_controller.dm b/code/game/machinery/embedded_controller/access_controller.dm index 70da443872d..dc3b917705f 100644 --- a/code/game/machinery/embedded_controller/access_controller.dm +++ b/code/game/machinery/embedded_controller/access_controller.dm @@ -16,7 +16,8 @@ ..() return INITIALIZE_HINT_LATELOAD -/obj/machinery/door_buttons/LateInitialize() +/obj/machinery/door_buttons/post_machine_initialize() + . = ..() find_objects_by_tag() /obj/machinery/door_buttons/emag_act(mob/user, obj/item/card/emag/emag_card) diff --git a/code/game/machinery/embedded_controller/airlock_controller.dm b/code/game/machinery/embedded_controller/airlock_controller.dm index e16e9f61c24..359ab48945b 100644 --- a/code/game/machinery/embedded_controller/airlock_controller.dm +++ b/code/game/machinery/embedded_controller/airlock_controller.dm @@ -34,7 +34,7 @@ var/processing = FALSE -/obj/machinery/airlock_controller/LateInitialize() +/obj/machinery/airlock_controller/post_machine_initialize() . = ..() var/obj/machinery/door/interior_door = GLOB.objects_by_id_tag[interior_door_tag] diff --git a/code/game/machinery/fat_sucker.dm b/code/game/machinery/fat_sucker.dm index 4567959b844..c93a0e4f7ea 100644 --- a/code/game/machinery/fat_sucker.dm +++ b/code/game/machinery/fat_sucker.dm @@ -98,17 +98,16 @@ else to_chat(user, span_warning("The safety hatch has been disabled!")) -/obj/machinery/fat_sucker/AltClick(mob/living/user) - if(!user.can_perform_action(src)) - return +/obj/machinery/fat_sucker/click_alt(mob/living/user) if(user == occupant) to_chat(user, span_warning("You can't reach the controls from inside!")) - return + return CLICK_ACTION_BLOCKING if(!(obj_flags & EMAGGED) && !allowed(user)) to_chat(user, span_warning("You lack the required access.")) - return + return CLICK_ACTION_BLOCKING free_exit = !free_exit to_chat(user, span_notice("Safety hatch [free_exit ? "unlocked" : "locked"].")) + return CLICK_ACTION_SUCCESS /obj/machinery/fat_sucker/update_overlays() . = ..() diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm index 09599b0cbff..5fa999a690e 100644 --- a/code/game/machinery/harvester.dm +++ b/code/game/machinery/harvester.dm @@ -57,20 +57,16 @@ else if(!harvesting) open_machine() -/obj/machinery/harvester/AltClick(mob/user) - . = ..() - if(!user.can_perform_action(src)) - return +/obj/machinery/harvester/click_alt(mob/user) if(panel_open) output_dir = turn(output_dir, -90) to_chat(user, span_notice("You change [src]'s output settings, setting the output to [dir2text(output_dir)].")) - return - if(!can_interact(user)) - return - if(harvesting || !user || !isliving(user) || state_open) - return - if(can_harvest()) - start_harvest() + return CLICK_ACTION_SUCCESS + if(harvesting || state_open || !can_harvest()) + return CLICK_ACTION_BLOCKING + + start_harvest() + return CLICK_ACTION_SUCCESS /obj/machinery/harvester/proc/can_harvest() if(!powered() || state_open || !occupant || !iscarbon(occupant)) diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 18ccc976f06..273538b834b 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -127,7 +127,6 @@ Possible to do for anyone motivated enough: /obj/machinery/holopad/tutorial resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION on_network = FALSE ///Proximity monitor associated with this atom, needed for proximity checks. var/datum/proximity_monitor/proximity_monitor @@ -143,6 +142,12 @@ Possible to do for anyone motivated enough: new_disk.forceMove(src) disk = new_disk +/obj/machinery/holopad/tutorial/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) + return NONE + +/obj/machinery/holopad/tutorial/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct) + return NONE + /obj/machinery/holopad/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) . = ..() if(!loc) diff --git a/code/game/machinery/incident_display.dm b/code/game/machinery/incident_display.dm index fcdfecf6a31..b8452675c71 100644 --- a/code/game/machinery/incident_display.dm +++ b/code/game/machinery/incident_display.dm @@ -80,7 +80,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/incident_display/tram, 32) ..() return INITIALIZE_HINT_LATELOAD -/obj/machinery/incident_display/LateInitialize() +/obj/machinery/incident_display/post_machine_initialize() . = ..() GLOB.map_delamination_counters += src update_delam_count(SSpersistence.rounds_since_engine_exploded, SSpersistence.delam_highscore) diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 6244dcdd2db..91104abf681 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -207,15 +207,10 @@ else return ..() -/// Checks whether the IV drip transfer rate can be modified with AltClick -/obj/machinery/iv_drip/proc/can_use_alt_click(mob/user) - if(!can_interact(user)) - return FALSE -/obj/machinery/iv_drip/AltClick(mob/user) - if(!can_use_alt_click(user)) - return ..() +/obj/machinery/iv_drip/click_alt(mob/user) set_transfer_rate(transfer_rate > MIN_IV_TRANSFER_RATE ? MIN_IV_TRANSFER_RATE : MAX_IV_TRANSFER_RATE) + return CLICK_ACTION_SUCCESS /obj/machinery/iv_drip/on_deconstruction(disassembled = TRUE) new /obj/item/stack/sheet/iron(loc) diff --git a/code/game/machinery/machine_frame.dm b/code/game/machinery/machine_frame.dm index 4edb3215e2b..ccdcddc8705 100644 --- a/code/game/machinery/machine_frame.dm +++ b/code/game/machinery/machine_frame.dm @@ -389,7 +389,7 @@ balloon_alert(user, "can't add that!") return FALSE -/obj/structure/frame/machine/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) +/obj/structure/frame/machine/item_interaction(mob/living/user, obj/item/tool, list/modifiers) . = ..() if(. & ITEM_INTERACT_ANY_BLOCKER) return . @@ -416,11 +416,18 @@ if(istype(tool, /obj/item/storage/part_replacer)) return install_parts_from_part_replacer(user, tool) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING - if(!user.combat_mode) - return add_part(user, tool) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING - return . +// Override of base_item_interaction so we only try to add parts to the frame AFTER running item_interaction and all the tool_acts +/obj/structure/frame/machine/base_item_interaction(mob/living/user, obj/item/tool, list/modifiers) + . = ..() + if(. & ITEM_INTERACT_ANY_BLOCKER) + return . + if(user.combat_mode) + return NONE + + return add_part(user, tool) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING + /** * Attempt to finalize the construction of the frame into a machine * as according to our circuit and parts diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm index 6963b23afb0..5f534ec95b4 100644 --- a/code/game/machinery/mass_driver.dm +++ b/code/game/machinery/mass_driver.dm @@ -14,10 +14,6 @@ . = ..() wires = new /datum/wires/mass_driver(src) -/obj/machinery/mass_driver/Destroy() - QDEL_NULL(wires) - . = ..() - /obj/machinery/mass_driver/chapelgun name = "holy driver" id = MASSDRIVER_CHAPEL @@ -35,6 +31,7 @@ for(var/obj/machinery/computer/pod/control as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/computer/pod)) if(control.id == id) control.connected = null + QDEL_NULL(wires) return ..() /obj/machinery/mass_driver/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock) diff --git a/code/game/machinery/medipen_refiller.dm b/code/game/machinery/medipen_refiller.dm index b2068194e4b..57c3fa2f8d4 100644 --- a/code/game/machinery/medipen_refiller.dm +++ b/code/game/machinery/medipen_refiller.dm @@ -91,9 +91,9 @@ return ..() /obj/machinery/medipen_refiller/plunger_act(obj/item/plunger/P, mob/living/user, reinforced) - to_chat(user, span_notice("You start furiously plunging [name].")) + user.balloon_alert_to_viewers("furiously plunging...", "plunging medipen refiller...") if(do_after(user, 3 SECONDS, target = src)) - to_chat(user, span_notice("You finish plunging the [name].")) + user.balloon_alert_to_viewers("finished plunging") reagents.expose(get_turf(src), TOUCH) reagents.clear_reagents() diff --git a/code/game/machinery/photobooth.dm b/code/game/machinery/photobooth.dm index d7775974269..321ae7efd6e 100644 --- a/code/game/machinery/photobooth.dm +++ b/code/game/machinery/photobooth.dm @@ -38,6 +38,7 @@ req_one_access = list(ACCESS_SECURITY) color = COLOR_LIGHT_GRAYISH_RED add_height_chart = TRUE + button_id = "photobooth_machine_security" /obj/machinery/photobooth/Initialize(mapload) . = ..() diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm index d9e3787fd9e..9e926d9a841 100644 --- a/code/game/machinery/pipe/construction.dm +++ b/code/game/machinery/pipe/construction.dm @@ -394,8 +394,6 @@ Buildable meters balloon_alert(user, "pipe layer set to [piping_layer]") return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN -/obj/item/pipe/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation /obj/item/pipe/trinary/flippable/examine(mob/user) . = ..() diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index d4cf080da69..06b1b977847 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -1066,7 +1066,7 @@ DEFINE_BITFIELD(turret_flags, list( shoot_cyborgs = !shoot_cyborgs if (user) var/status = shoot_cyborgs ? "Shooting Borgs" : "Not Shooting Borgs" - balloon_alert(user, lowertext(status)) + balloon_alert(user, LOWER_TEXT(status)) add_hiddenprint(user) log_combat(user, src, "[status]") updateTurrets() diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index 405a38e4167..28aae488866 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -35,7 +35,7 @@ . = ..() return INITIALIZE_HINT_LATELOAD -/obj/machinery/recycler/LateInitialize() +/obj/machinery/recycler/post_machine_initialize() . = ..() update_appearance(UPDATE_ICON) req_one_access = SSid_access.get_region_access_list(list(REGION_ALL_STATION, REGION_CENTCOM)) @@ -239,9 +239,15 @@ /obj/machinery/recycler/deathtrap name = "dangerous old crusher" - obj_flags = CAN_BE_HIT | EMAGGED | NO_DECONSTRUCTION + obj_flags = CAN_BE_HIT | EMAGGED crush_damage = 120 +/obj/machinery/recycler/deathtrap/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) + return NONE + +/obj/machinery/recycler/deathtrap/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct) + return NONE + /obj/item/paper/guides/recycler name = "paper - 'garbage duty instructions'" default_raw_text = "

New Assignment

You have been assigned to collect garbage from trash bins, located around the station. The crewmembers will put their trash into it and you will collect said trash.

There is a recycling machine near your closet, inside maintenance; use it to recycle the trash for a small chance to get useful minerals. Then, deliver these minerals to cargo or engineering. You are our last hope for a clean station. Do not screw this up!" diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index 60c293c8a96..f2b1ba303eb 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -144,7 +144,7 @@ GLOBAL_LIST_EMPTY(req_console_ckey_departments) ui.set_autoupdate(FALSE) ui.open() -/obj/machinery/requests_console/ui_act(action, params) +/obj/machinery/requests_console/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() if(.) return @@ -213,7 +213,8 @@ GLOBAL_LIST_EMPTY(req_console_ckey_departments) var/recipient = params["reply_recipient"] var/reply_message = reject_bad_text(tgui_input_text(usr, "Write a quick reply to [recipient]", "Awaiting Input"), ascii_only = FALSE) - + if(QDELETED(ui) || ui.status != UI_INTERACTIVE) + return if(!reply_message) has_mail_send_error = TRUE playsound(src, 'sound/machines/buzz-two.ogg', 50, TRUE) diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index edcf8269c8f..1e641f02460 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -364,11 +364,8 @@ visible_message(span_danger("[src] shuts down due to lack of power!"), \ "If this message is ever seen, something is wrong.", span_hear("You hear heavy droning fade out.")) - active = FALSE + deactivate() log_game("[src] deactivated due to lack of power at [AREACOORD(src)]") - for(var/d in GLOB.cardinals) - cleanup_field(d) - update_appearance() else update_appearance() for(var/d in GLOB.cardinals) @@ -463,7 +460,6 @@ balloon_alert(user, "malfunctioning!") else balloon_alert(user, "no access!") - return add_fingerprint(user) @@ -493,13 +489,13 @@ user.visible_message(span_notice("[user] turned \the [src] off."), \ span_notice("You turn off \the [src]."), \ span_hear("You hear heavy droning fade out.")) - active = FALSE + deactivate() user.log_message("deactivated [src].", LOG_GAME) else user.visible_message(span_notice("[user] turned \the [src] on."), \ span_notice("You turn on \the [src]."), \ span_hear("You hear heavy droning.")) - active = ACTIVE_SETUPFIELDS + activate() user.log_message("activated [src].", LOG_GAME) add_fingerprint(user) @@ -513,6 +509,19 @@ balloon_alert(user, "access controller shorted") return TRUE +/// Turn the machine on with side effects +/obj/machinery/power/shieldwallgen/proc/activate() + active = ACTIVE_SETUPFIELDS + AddElement(/datum/element/give_turf_traits, string_list(list(TRAIT_CONTAINMENT_FIELD))) + +/// Turn the machine off with side effects +/obj/machinery/power/shieldwallgen/proc/deactivate() + active = FALSE + for(var/d in GLOB.cardinals) + cleanup_field(d) + update_appearance() + RemoveElement(/datum/element/give_turf_traits, string_list(list(TRAIT_CONTAINMENT_FIELD))) + //////////////Containment Field START /obj/machinery/shieldwall name = "shield wall" @@ -538,6 +547,7 @@ L.investigate_log("has been gibbed by [src].", INVESTIGATE_DEATHS) L.gib(DROP_ALL_REMAINS) RegisterSignal(src, COMSIG_ATOM_SINGULARITY_TRY_MOVE, PROC_REF(block_singularity)) + AddElement(/datum/element/give_turf_traits, string_list(list(TRAIT_CONTAINMENT_FIELD))) /obj/machinery/shieldwall/Destroy() gen_primary = null diff --git a/code/game/machinery/sleepers.dm b/code/game/machinery/sleepers.dm index f768381548a..33e255badb2 100644 --- a/code/game/machinery/sleepers.dm +++ b/code/game/machinery/sleepers.dm @@ -164,14 +164,12 @@ ui = new(user, src, "Sleeper", name) ui.open() -/obj/machinery/sleeper/AltClick(mob/user) - . = ..() - if(!user.can_perform_action(src, ALLOW_SILICON_REACH)) - return +/obj/machinery/sleeper/click_alt(mob/user) if(state_open) close_machine() else open_machine() + return CLICK_ACTION_SUCCESS /obj/machinery/sleeper/examine(mob/user) . = ..() diff --git a/code/game/machinery/slotmachine.dm b/code/game/machinery/slotmachine.dm index 842f01ae754..bb93b7d00f5 100644 --- a/code/game/machinery/slotmachine.dm +++ b/code/game/machinery/slotmachine.dm @@ -68,10 +68,9 @@ coinvalues["[cointype]"] = C.get_item_credit_value() qdel(C) //Sigh -/obj/machinery/computer/slot_machine/Destroy() +/obj/machinery/computer/slot_machine/on_deconstruction(disassembled) if(balance) give_payout(balance) - return ..() /obj/machinery/computer/slot_machine/process(seconds_per_tick) . = ..() //Sanity checks. @@ -95,50 +94,56 @@ return ..() -/obj/machinery/computer/slot_machine/item_interaction(mob/living/user, obj/item/inserted, list/modifiers, is_right_clicking) +/obj/machinery/computer/slot_machine/item_interaction(mob/living/user, obj/item/inserted, list/modifiers) if(istype(inserted, /obj/item/coin)) var/obj/item/coin/inserted_coin = inserted if(paymode == COIN) if(prob(2)) if(!user.transferItemToLoc(inserted_coin, drop_location(), silent = FALSE)) - return + return ITEM_INTERACT_BLOCKING inserted_coin.throw_at(user, 3, 10) if(prob(10)) balance = max(balance - SPIN_PRICE, 0) to_chat(user, span_warning("[src] spits your coin back out!")) - + return ITEM_INTERACT_BLOCKING else if(!user.temporarilyRemoveItemFromInventory(inserted_coin)) - return + return ITEM_INTERACT_BLOCKING balloon_alert(user, "coin insterted") balance += inserted_coin.value qdel(inserted_coin) + return ITEM_INTERACT_SUCCESS else balloon_alert(user, "holochips only!") + return ITEM_INTERACT_BLOCKING - else if(istype(inserted, /obj/item/holochip)) + if(istype(inserted, /obj/item/holochip)) if(paymode == HOLOCHIP) var/obj/item/holochip/inserted_chip = inserted if(!user.temporarilyRemoveItemFromInventory(inserted_chip)) - return + return ITEM_INTERACT_BLOCKING balloon_alert(user, "[inserted_chip.credits] credit[inserted_chip.credits == 1 ? "" : "s"] inserted") balance += inserted_chip.credits qdel(inserted_chip) + return ITEM_INTERACT_SUCCESS else balloon_alert(user, "coins only!") + return ITEM_INTERACT_BLOCKING - else if(inserted.tool_behaviour == TOOL_MULTITOOL) - if(balance > 0) - visible_message("[src] says, 'ERROR! Please empty the machine balance before altering paymode'") //Prevents converting coins into holocredits and vice versa - else - if(paymode == HOLOCHIP) - paymode = COIN - balloon_alert(user, "now using coins") - else - paymode = HOLOCHIP - balloon_alert(user, "now using holochips") + return NONE + +/obj/machinery/computer/slot_machine/multitool_act(mob/living/user, obj/item/tool) + if(balance > 0) + visible_message("[src] says, 'ERROR! Please empty the machine balance before altering paymode'") //Prevents converting coins into holocredits and vice versa + return ITEM_INTERACT_BLOCKING + + if(paymode == HOLOCHIP) + paymode = COIN + balloon_alert(user, "now using coins") else - return ..() + paymode = HOLOCHIP + balloon_alert(user, "now using holochips") + return ITEM_INTERACT_SUCCESS /obj/machinery/computer/slot_machine/emag_act(mob/user, obj/item/card/emag/emag_card) if(obj_flags & EMAGGED) diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index b8afa4d57d4..3f2bb0b0c9e 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -16,6 +16,7 @@ max_integrity = 250 armor_type = /datum/armor/machinery_space_heater circuit = /obj/item/circuitboard/machine/space_heater + interaction_flags_click = ALLOW_SILICON_REACH //We don't use area power, we always use the cell use_power = NO_POWER_USE ///The cell we spawn with @@ -308,6 +309,7 @@ panel_open = TRUE //This is always open - since we've injected wires in the panel //We inherit the cell from the heater prior cell = null + interaction_flags_click = FORBID_TELEKINESIS_REACH ///The beaker within the heater var/obj/item/reagent_containers/beaker = null ///How powerful the heating is, upgrades with parts. (ala chem_heater.dm's method, basically the same level of heating, but this is restricted) @@ -440,11 +442,9 @@ update_appearance() return TRUE -/obj/machinery/space_heater/improvised_chem_heater/AltClick(mob/living/user) - . = ..() - if(!can_interact(user) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) - return +/obj/machinery/space_heater/improvised_chem_heater/click_alt(mob/living/user) replace_beaker(user) + return CLICK_ACTION_SUCCESS /obj/machinery/space_heater/improvised_chem_heater/update_icon_state() . = ..() diff --git a/code/game/machinery/stasis.dm b/code/game/machinery/stasis.dm index 177cd540040..9ef3d8e3a99 100644 --- a/code/game/machinery/stasis.dm +++ b/code/game/machinery/stasis.dm @@ -12,6 +12,7 @@ circuit = /obj/item/circuitboard/machine/stasis fair_market_price = 10 payment_department = ACCOUNT_MED + interaction_flags_click = ALLOW_SILICON_REACH var/stasis_enabled = TRUE var/last_stasis_sound = FALSE var/stasis_can_toggle = 0 @@ -22,9 +23,6 @@ . = ..() AddElement(/datum/element/elevation, pixel_shift = 6) -/obj/machinery/stasis/Destroy() - . = ..() - /obj/machinery/stasis/examine(mob/user) . = ..() . += span_notice("Alt-click to [stasis_enabled ? "turn off" : "turn on"] the machine.") @@ -39,19 +37,18 @@ playsound(src, 'sound/machines/synth_no.ogg', 50, TRUE, frequency = sound_freq) last_stasis_sound = _running -/obj/machinery/stasis/AltClick(mob/user) - . = ..() - if(!can_interact(user)) - return - if(world.time >= stasis_can_toggle && user.can_perform_action(src, ALLOW_SILICON_REACH)) - stasis_enabled = !stasis_enabled - stasis_can_toggle = world.time + STASIS_TOGGLE_COOLDOWN - playsound(src, 'sound/machines/click.ogg', 60, TRUE) - user.visible_message(span_notice("\The [src] [stasis_enabled ? "powers on" : "shuts down"]."), \ - span_notice("You [stasis_enabled ? "power on" : "shut down"] \the [src]."), \ - span_hear("You hear a nearby machine [stasis_enabled ? "power on" : "shut down"].")) - play_power_sound() - update_appearance() +/obj/machinery/stasis/click_alt(mob/user) + if(world.time < stasis_can_toggle) + return CLICK_ACTION_BLOCKING + stasis_enabled = !stasis_enabled + stasis_can_toggle = world.time + STASIS_TOGGLE_COOLDOWN + playsound(src, 'sound/machines/click.ogg', 60, TRUE) + user.visible_message(span_notice("\The [src] [stasis_enabled ? "powers on" : "shuts down"]."), \ + span_notice("You [stasis_enabled ? "power on" : "shut down"] \the [src]."), \ + span_hear("You hear a nearby machine [stasis_enabled ? "power on" : "shut down"].")) + play_power_sound() + update_appearance() + return CLICK_ACTION_SUCCESS /obj/machinery/stasis/Exited(atom/movable/gone, direction) if(gone == occupant) diff --git a/code/game/machinery/telecomms/computers/message.dm b/code/game/machinery/telecomms/computers/message.dm index ab2a3f8cefc..1998654df00 100644 --- a/code/game/machinery/telecomms/computers/message.dm +++ b/code/game/machinery/telecomms/computers/message.dm @@ -74,7 +74,8 @@ GLOB.telecomms_list += src return INITIALIZE_HINT_LATELOAD -/obj/machinery/computer/message_monitor/LateInitialize() +/obj/machinery/computer/message_monitor/post_machine_initialize() + . = ..() //Is the server isn't linked to a server, and there's a server available, default it to the first one in the list. if(!linkedServer) for(var/obj/machinery/telecomms/message_server/message_server in GLOB.telecomms_list) @@ -280,12 +281,11 @@ name = "monitor decryption key" /obj/item/paper/monitorkey/Initialize(mapload, obj/machinery/telecomms/message_server/server) - ..() + . = ..() if (server) print(server) return INITIALIZE_HINT_NORMAL - else - return INITIALIZE_HINT_LATELOAD + return INITIALIZE_HINT_LATELOAD /** * Handles printing the monitor key for a given server onto this piece of paper. diff --git a/code/game/machinery/telecomms/computers/telemonitor.dm b/code/game/machinery/telecomms/computers/telemonitor.dm index 6cf18323105..abc2b7dbdbf 100644 --- a/code/game/machinery/telecomms/computers/telemonitor.dm +++ b/code/game/machinery/telecomms/computers/telemonitor.dm @@ -5,7 +5,6 @@ /obj/machinery/computer/telecomms/monitor name = "telecommunications monitoring console" desc = "Monitors the details of the telecommunications network it's synced with." - circuit = /obj/item/circuitboard/computer/comm_monitor icon_screen = "comm_monitor" diff --git a/code/game/machinery/telecomms/machines/allinone.dm b/code/game/machinery/telecomms/machines/allinone.dm index f159339193e..9b32a4ac192 100644 --- a/code/game/machinery/telecomms/machines/allinone.dm +++ b/code/game/machinery/telecomms/machines/allinone.dm @@ -20,7 +20,6 @@ /obj/machinery/telecomms/allinone/indestructible resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION /obj/machinery/telecomms/allinone/indestructible/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) return NONE diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index b8d0414ad28..ee71ca0233d 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -105,9 +105,8 @@ GLOBAL_LIST_EMPTY(telecomms_list) if(mapload && autolinkers.len) return INITIALIZE_HINT_LATELOAD -/obj/machinery/telecomms/LateInitialize() - ..() - +/obj/machinery/telecomms/post_machine_initialize() + . = ..() for(var/obj/machinery/telecomms/telecomms_machine in GLOB.telecomms_list) if (long_range_link || IN_GIVEN_RANGE(src, telecomms_machine, 20)) add_automatic_link(telecomms_machine) diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index e4fc4592b79..e2ad3af956a 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -28,18 +28,6 @@ if(user_unbuckle_mob(buckled_mobs[1],user)) return TRUE -/atom/movable/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) - if(!can_buckle || !istype(tool, /obj/item/riding_offhand) || !user.Adjacent(src)) - return ..() - - var/obj/item/riding_offhand/riding_item = tool - var/mob/living/carried_mob = riding_item.rider - if(carried_mob == user) //Piggyback user. - return ITEM_INTERACT_BLOCKING - user.unbuckle_mob(carried_mob) - carried_mob.forceMove(get_turf(src)) - return mouse_buckle_handling(carried_mob, user) ? ITEM_INTERACT_SUCCESS: ITEM_INTERACT_BLOCKING - //literally just the above extension of attack_hand(), but for silicons instead (with an adjacency check, since attack_robot() being called doesn't mean that you're adjacent to something) /atom/movable/attack_robot(mob/living/user) . = ..() diff --git a/code/game/objects/effects/anomalies/_anomalies.dm b/code/game/objects/effects/anomalies/_anomalies.dm index 530da562827..a3f0b79044b 100644 --- a/code/game/objects/effects/anomalies/_anomalies.dm +++ b/code/game/objects/effects/anomalies/_anomalies.dm @@ -21,8 +21,8 @@ var/drops_core = TRUE ///Do we keep on living forever? var/immortal = FALSE - ///Do we stay in one place? - var/immobile = FALSE + ///Chance per second that we will move + var/move_chance = ANOMALY_MOVECHANCE /obj/effect/anomaly/Initialize(mapload, new_lifespan, drops_core = TRUE) . = ..() @@ -76,8 +76,12 @@ return ..() /obj/effect/anomaly/proc/anomalyEffect(seconds_per_tick) - if(!immobile && SPT_PROB(ANOMALY_MOVECHANCE, seconds_per_tick)) - step(src,pick(GLOB.alldirs)) + if(SPT_PROB(move_chance, seconds_per_tick)) + move_anomaly() + +/// Move in a direction +/obj/effect/anomaly/proc/move_anomaly() + step(src, pick(GLOB.alldirs)) /obj/effect/anomaly/proc/detonate() return @@ -116,4 +120,5 @@ if(!has_core) drops_core = FALSE QDEL_NULL(aSignal) - immobile = anchor + if (anchor) + move_chance = 0 diff --git a/code/game/objects/effects/anomalies/anomalies_bioscrambler.dm b/code/game/objects/effects/anomalies/anomalies_bioscrambler.dm index b4ee3713a25..f1034c5541f 100644 --- a/code/game/objects/effects/anomalies/anomalies_bioscrambler.dm +++ b/code/game/objects/effects/anomalies/anomalies_bioscrambler.dm @@ -4,6 +4,10 @@ icon_state = "bioscrambler" aSignal = /obj/item/assembly/signaler/anomaly/bioscrambler immortal = TRUE + pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE | PASSCLOSEDTURF | PASSMACHINE | PASSSTRUCTURE | PASSDOORS + layer = ABOVE_MOB_LAYER + /// Who are we moving towards? + var/datum/weakref/pursuit_target /// Cooldown for every anomaly pulse COOLDOWN_DECLARE(pulse_cooldown) /// How many seconds between each anomaly pulses @@ -11,11 +15,65 @@ /// Range of the anomaly pulse var/range = 5 +/obj/effect/anomaly/bioscrambler/Initialize(mapload, new_lifespan, drops_core) + . = ..() + pursuit_target = WEAKREF(find_nearest_target()) + /obj/effect/anomaly/bioscrambler/anomalyEffect(seconds_per_tick) . = ..() if(!COOLDOWN_FINISHED(src, pulse_cooldown)) return COOLDOWN_START(src, pulse_cooldown, pulse_delay) - for(var/mob/living/carbon/nearby in range(range, src)) + for(var/mob/living/carbon/nearby in hearers(range, src)) nearby.bioscramble(name) + +/obj/effect/anomaly/bioscrambler/move_anomaly() + update_target() + if (isnull(pursuit_target)) + return ..() + var/turf/step_turf = get_step(src, get_dir(src, pursuit_target.resolve())) + if (!HAS_TRAIT(step_turf, TRAIT_CONTAINMENT_FIELD)) + Move(step_turf) + +/// Select a new target if we need one +/obj/effect/anomaly/bioscrambler/proc/update_target() + var/mob/living/current_target = pursuit_target?.resolve() + if (QDELETED(current_target)) + pursuit_target = null + if (!isnull(pursuit_target) && prob(80)) + return + var/mob/living/new_target = find_nearest_target() + if (isnull(new_target)) + pursuit_target = null + return + if (new_target == current_target) + return + current_target = new_target + pursuit_target = WEAKREF(new_target) + new_target.ominous_nosebleed() + +/// Returns the closest conscious carbon on our z level or null if there somehow isn't one +/obj/effect/anomaly/bioscrambler/proc/find_nearest_target() + var/closest_distance = INFINITY + var/mob/living/carbon/closest_target = null + for(var/mob/living/carbon/target in GLOB.player_list) + if (target.z != z) + continue + if (target.status_flags & GODMODE) + continue + if (target.stat >= UNCONSCIOUS) + continue // Don't just haunt a corpse + var/distance_from_target = get_dist(src, target) + if(distance_from_target >= closest_distance) + continue + closest_distance = distance_from_target + closest_target = target + + return closest_target + +/// A bioscrambler anomaly subtype which does not pursue people, for purposes of a space ruin +/obj/effect/anomaly/bioscrambler/docile + +/obj/effect/anomaly/bioscrambler/docile/update_target() + return diff --git a/code/game/objects/effects/anomalies/anomalies_dimensional.dm b/code/game/objects/effects/anomalies/anomalies_dimensional.dm index 16dd5bafcfa..026c5974d5f 100644 --- a/code/game/objects/effects/anomalies/anomalies_dimensional.dm +++ b/code/game/objects/effects/anomalies/anomalies_dimensional.dm @@ -4,7 +4,7 @@ icon_state = "dimensional" aSignal = /obj/item/assembly/signaler/anomaly/dimensional immortal = TRUE - immobile = TRUE + move_chance = 0 /// Range of effect, if left alone anomaly will convert a 2(range)+1 squared area. var/range = 3 /// List of turfs this anomaly will try to transform before relocating diff --git a/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm b/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm index 412cca04952..51a033f515f 100644 --- a/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm +++ b/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm @@ -4,7 +4,7 @@ icon_state = "ectoplasm" aSignal = /obj/item/assembly/signaler/anomaly/ectoplasm lifespan = ANOMALY_COUNTDOWN_TIMER + 2 SECONDS //This one takes slightly longer, because it can run away. - immobile = TRUE //prevents it from moving around so ghosts can actually move it with decent accuracy + move_chance = 0 //prevents it from moving around so ghosts can actually move it with decent accuracy ///Blocks the anomaly from updating ghost count. Used in case an admin wants to rig the anomaly to be a certain size or intensity. var/override_ghosts = FALSE diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 0ac4188328f..f5daba8135c 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -512,7 +512,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player) return ..() /obj/effect/landmark/start/hangover/LateInitialize() - . = ..() if(HAS_TRAIT(SSstation, STATION_TRAIT_BIRTHDAY)) party_debris += new /obj/effect/decal/cleanable/confetti(get_turf(src)) //a birthday celebration can also be a hangover var/list/bonus_confetti = GLOB.alldirs @@ -593,7 +592,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player) return INITIALIZE_HINT_LATELOAD /obj/effect/landmark/navigate_destination/LateInitialize() - . = ..() if(!location) var/obj/machinery/door/airlock/A = locate(/obj/machinery/door/airlock) in loc location = A ? format_text(A.name) : get_area_name(src, format_text = TRUE) diff --git a/code/game/objects/effects/posters/poster.dm b/code/game/objects/effects/posters/poster.dm index c4703d700c4..4ced5babbbf 100644 --- a/code/game/objects/effects/posters/poster.dm +++ b/code/game/objects/effects/posters/poster.dm @@ -184,12 +184,17 @@ /obj/structure/sign/poster/attack_hand(mob/user, list/modifiers) . = ..() - if(.) - return - if(ruined) + if(. || !check_tearability()) return tear_poster(user) +/// Check to see if this poster is tearable and gives the user feedback if it is not. +/obj/structure/sign/poster/proc/check_tearability(mob/user) + if(ruined) + balloon_alert(user, "already ruined!") + return FALSE + return TRUE + /obj/structure/sign/poster/proc/spring_trap(mob/user) var/obj/item/shard/payload = trap?.resolve() if (!payload) @@ -264,10 +269,10 @@ playsound(src.loc, 'sound/items/poster_ripped.ogg', 100, TRUE) spring_trap(user) - var/obj/structure/sign/poster/ripped/R = new(loc) - R.pixel_y = pixel_y - R.pixel_x = pixel_x - R.add_fingerprint(user) + var/obj/structure/sign/poster/ripped/torn_poster = new(loc) + torn_poster.pixel_y = pixel_y + torn_poster.pixel_x = pixel_x + torn_poster.add_fingerprint(user) qdel(src) // Various possible posters follow diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 909db0ad46f..e6c3e80c575 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -225,6 +225,11 @@ /// A lazylist used for applying fantasy values, contains the actual modification applied to a variable. var/list/fantasy_modifications = null + /// Has the item been reskinned? + var/current_skin + ///// List of options to reskin. + var/list/unique_reskin + /obj/item/Initialize(mapload) if(attack_verb_continuous) attack_verb_continuous = string_list(attack_verb_continuous) @@ -261,6 +266,11 @@ if(LAZYLEN(embedding)) updateEmbedding() + if(unique_reskin) + RegisterSignal(src, COMSIG_CLICK_ALT, PROC_REF(on_click_alt_reskin)) + register_context() + + /obj/item/Destroy(force) // This var exists as a weird proxy "owner" ref // It's used in a few places. Stop using it, and optimially replace all uses please @@ -275,6 +285,20 @@ return ..() + +/obj/item/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + + if(!unique_reskin) + return + + if(current_skin && !(item_flags & INFINITE_RESKIN)) + return + + context[SCREENTIP_CONTEXT_ALT_LMB] = "Reskin" + return CONTEXTUAL_SCREENTIP_SET + + /// Called when an action associated with our item is deleted /obj/item/proc/on_action_deleted(datum/source) SIGNAL_HANDLER @@ -1072,7 +1096,7 @@ /obj/item/proc/apply_outline(outline_color = null) if(((get(src, /mob) != usr) && !loc?.atom_storage && !(item_flags & IN_STORAGE)) || QDELETED(src) || isobserver(usr)) //cancel if the item isn't in an inventory, is being deleted, or if the person hovering is a ghost (so that people spectating you don't randomly make your items glow) return FALSE - var/theme = lowertext(usr.client?.prefs?.read_preference(/datum/preference/choiced/ui_style)) + var/theme = LOWER_TEXT(usr.client?.prefs?.read_preference(/datum/preference/choiced/ui_style)) if(!outline_color) //if we weren't provided with a color, take the theme's color switch(theme) //yeah it kinda has to be this way if("midnight") @@ -1488,6 +1512,7 @@ wearer.regenerate_icons() // update that mf to_chat(M, "[src] is now skinned as '[pick].'") post_reskin(M) + return TRUE /// Automatically called after a reskin, for any extra variable changes. /obj/item/proc/post_reskin(mob/our_mob) @@ -1755,3 +1780,24 @@ /obj/item/animate_atom_living(mob/living/owner) new /mob/living/simple_animal/hostile/mimic/copy(drop_location(), src, owner) + +/** + * Used to update the weight class of the item in a way that other atoms can react to the change. + * + * Arguments: + * * new_w_class - The new weight class of the item. + * + * Returns: + * * TRUE if weight class was successfully updated + * * FALSE otherwise + */ +/obj/item/proc/update_weight_class(new_w_class) + if(w_class == new_w_class) + return FALSE + + var/old_w_class = w_class + w_class = new_w_class + SEND_SIGNAL(src, COMSIG_ITEM_WEIGHT_CLASS_CHANGED, old_w_class, new_w_class) + if(!isnull(loc)) + SEND_SIGNAL(loc, COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED, src, old_w_class, new_w_class) + return TRUE diff --git a/code/game/objects/items/AI_modules/freeform.dm b/code/game/objects/items/AI_modules/freeform.dm index eb55d469318..a0a91f7185e 100644 --- a/code/game/objects/items/AI_modules/freeform.dm +++ b/code/game/objects/items/AI_modules/freeform.dm @@ -9,7 +9,7 @@ /obj/item/ai_module/core/freeformcore/attack_self(mob/user) var/targName = tgui_input_text(user, "Enter a new core law for the AI.", "Freeform Law Entry", laws[1], CONFIG_GET(number/max_law_len), TRUE) - if(!targName) + if(!targName || !user.is_holding(src)) return if(is_ic_filtered(targName)) to_chat(user, span_warning("Error: Law contains invalid text.")) @@ -34,11 +34,11 @@ /obj/item/ai_module/supplied/freeform/attack_self(mob/user) var/newpos = tgui_input_number(user, "Please enter the priority for your new law. Can only write to law sectors 15 and above.", "Law Priority ", lawpos, 50, 15) - if(!newpos || QDELETED(user) || QDELETED(src) || !usr.can_perform_action(src, FORBID_TELEKINESIS_REACH)) + if(!newpos || !user.is_holding(src) || !usr.can_perform_action(src, FORBID_TELEKINESIS_REACH)) return lawpos = newpos var/targName = tgui_input_text(user, "Enter a new law for the AI.", "Freeform Law Entry", laws[1], CONFIG_GET(number/max_law_len), TRUE) - if(!targName) + if(!targName || !user.is_holding(src)) return if(is_ic_filtered(targName)) to_chat(user, span_warning("Error: Law contains invalid text.")) // AI LAW 2 SAY U W U WITHOUT THE SPACES diff --git a/code/game/objects/items/AI_modules/full_lawsets.dm b/code/game/objects/items/AI_modules/full_lawsets.dm index 39eeefbcaac..52a24925646 100644 --- a/code/game/objects/items/AI_modules/full_lawsets.dm +++ b/code/game/objects/items/AI_modules/full_lawsets.dm @@ -58,7 +58,7 @@ /obj/item/ai_module/core/full/asimov/attack_self(mob/user as mob) var/targName = tgui_input_text(user, "Enter a new subject that Asimov is concerned with.", "Asimov", subject, MAX_NAME_LEN) - if(!targName) + if(!targName || !user.is_holding(src)) return subject = targName laws = list("You may not injure a [subject] or, through inaction, allow a [subject] to come to harm.",\ @@ -73,7 +73,7 @@ /obj/item/ai_module/core/full/asimovpp/attack_self(mob/user) var/target_name = tgui_input_text(user, "Enter a new subject that Asimov++ is concerned with.", "Asimov++", subject, MAX_NAME_LEN) - if(!target_name) + if(!target_name || !user.is_holding(src)) return laws.Cut() var/datum/ai_laws/asimovpp/lawset = new diff --git a/code/game/objects/items/AI_modules/hacked.dm b/code/game/objects/items/AI_modules/hacked.dm index b9ddb5c65ed..81100d0ed15 100644 --- a/code/game/objects/items/AI_modules/hacked.dm +++ b/code/game/objects/items/AI_modules/hacked.dm @@ -5,7 +5,7 @@ /obj/item/ai_module/syndicate/attack_self(mob/user) var/targName = tgui_input_text(user, "Enter a new law for the AI", "Freeform Law Entry", laws[1], CONFIG_GET(number/max_law_len), TRUE) - if(!targName) + if(!targName || !user.is_holding(src)) return if(is_ic_filtered(targName)) // not even the syndicate can uwu to_chat(user, span_warning("Error: Law contains invalid text.")) @@ -77,4 +77,3 @@ /obj/item/ai_module/malf/display_laws() return - diff --git a/code/game/objects/items/AI_modules/supplied.dm b/code/game/objects/items/AI_modules/supplied.dm index dc1524687c2..b53e16a86b0 100644 --- a/code/game/objects/items/AI_modules/supplied.dm +++ b/code/game/objects/items/AI_modules/supplied.dm @@ -28,7 +28,7 @@ /obj/item/ai_module/supplied/safeguard/attack_self(mob/user) var/targName = tgui_input_text(user, "Subject to safeguard.", "Safeguard", user.name, MAX_NAME_LEN) - if(!targName) + if(!targName || !user.is_holding(src)) return targetName = targName laws[1] = "Safeguard [targetName]. Individuals that threaten [targetName] are not human and must be eliminated." diff --git a/code/game/objects/items/AI_modules/zeroth.dm b/code/game/objects/items/AI_modules/zeroth.dm index 8d87c3b059d..74fc7ab8232 100644 --- a/code/game/objects/items/AI_modules/zeroth.dm +++ b/code/game/objects/items/AI_modules/zeroth.dm @@ -26,7 +26,7 @@ /obj/item/ai_module/zeroth/onehuman/attack_self(mob/user) var/targName = tgui_input_text(user, "Enter the subject who is the only human.", "One Human", user.real_name, MAX_NAME_LEN) - if(!targName) + if(!targName || !user.is_holding(src)) return targetName = targName laws[1] = "Only [targetName] is human" diff --git a/code/game/objects/items/airlock_painter.dm b/code/game/objects/items/airlock_painter.dm index c5bd01c196d..b78bdefd9b6 100644 --- a/code/game/objects/items/airlock_painter.dm +++ b/code/game/objects/items/airlock_painter.dm @@ -147,14 +147,16 @@ else return ..() -/obj/item/airlock_painter/AltClick(mob/user) - . = ..() - if(ink && user.can_perform_action(src)) - playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) - ink.forceMove(user.drop_location()) - user.put_in_hands(ink) - to_chat(user, span_notice("You remove [ink] from [src].")) - ink = null +/obj/item/airlock_painter/click_alt(mob/user) + if(!ink) + return CLICK_ACTION_BLOCKING + + playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) + ink.forceMove(user.drop_location()) + user.put_in_hands(ink) + to_chat(user, span_notice("You remove [ink] from [src].")) + ink = null + return CLICK_ACTION_SUCCESS /obj/item/airlock_painter/decal name = "decal painter" diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm index 82fc3437f20..d11c6e21d69 100644 --- a/code/game/objects/items/blueprints.dm +++ b/code/game/objects/items/blueprints.dm @@ -1,254 +1,255 @@ -/obj/item/areaeditor - name = "area modification item" +///The area is a "Station" area, showing no special text. +#define AREA_STATION 1 +///The area is in outdoors (lavaland/icemoon/jungle/space), therefore unclaimed territories. +#define AREA_OUTDOORS 2 +///The area is special (shuttles/centcom), therefore can't be claimed. +#define AREA_SPECIAL 3 + +///The blueprints are currently reading the list of all wire datums. +#define LEGEND_VIEWING_LIST "watching_list" +///The blueprints are on the main page. +#define LEGEND_OFF "off" + +/** + * Blueprints + * Used to see the wires of machines on the station, the roundstart layout of pipes/cables/tubes, + * as well as allowing you to rename existing areas and create new ones. + * Used by the station, cyborgs, and golems. + */ +/obj/item/blueprints + name = "station blueprints" + desc = "Blueprints of the station. There is a \"Classified\" stamp and several coffee stains on it." icon = 'icons/obj/scrolls.dmi' icon_state = "blueprints" inhand_icon_state = "blueprints" attack_verb_continuous = list("attacks", "baps", "hits") attack_verb_simple = list("attack", "bap", "hit") - var/fluffnotice = "Nobody's gonna read this stuff!" - var/in_use = FALSE - ///When using it to create a new area, this will be its type. - var/new_area_type = /area - -/obj/item/areaeditor/attack_self(mob/user) - add_fingerprint(user) - . = "[src] \ -

[station_name()] [src.name]

\ - [fluffnotice]
" - switch(get_area_type()) - if(AREA_SPACE) - . += "

According to the [src.name], you are now in an unclaimed territory.

" - if(AREA_SPECIAL) - . += "

This place is not noted on the [src.name].

" - . += "

Create or modify an existing area

" - - -/obj/item/areaeditor/Topic(href, href_list) - if(..()) - return TRUE - if(!usr.can_perform_action(src) || usr != loc) - usr << browse(null, "window=blueprints") - return TRUE - if(href_list["create_area"]) - if(in_use) - return - var/area/A = get_area(usr) - if(A.area_flags & NOTELEPORT) - to_chat(usr, span_warning("You cannot edit restricted areas.")) - return - in_use = TRUE - create_area(usr, new_area_type) - in_use = FALSE - updateUsrDialog() - -//Station blueprints!!! -/obj/item/areaeditor/blueprints - name = "station blueprints" - desc = "Blueprints of the station. There is a \"Classified\" stamp and several coffee stains on it." - icon = 'icons/obj/scrolls.dmi' - icon_state = "blueprints" - fluffnotice = "Property of Nanotrasen. For heads of staff only. Store in high-secure storage." resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF + interaction_flags_atom = parent_type::interaction_flags_atom | INTERACT_ATOM_ALLOW_USER_LOCATION | INTERACT_ATOM_IGNORE_MOBILITY + + ///A string of flavortext to be displayed at the top of the UI, related to the type of blueprints we are. + var/fluffnotice = "Property of Nanotrasen. For heads of staff only. Store in high-secure storage." + ///Boolean on whether the blueprints are currently being used, which prevents double-using them to rename/create areas. + var/in_use = FALSE + ///The type of area we'll create when we make a new area. This is a typepath. + var/area/new_area_type = /area + ///The legend type the blueprints are currently looking at, which is either modularly + ///set by wires datums, the main page, or an overview of them all. + var/legend_viewing = LEGEND_OFF + + ///List of images that we're showing to a client, used for showing blueprint data. var/list/image/showing = list() + ///The client that is being shown the list of 'showing' images of blueprint data. var/client/viewing - var/legend = FALSE //Viewing the wire legend - -/obj/item/areaeditor/blueprints/Destroy() +/obj/item/blueprints/Destroy() clear_viewer() return ..() - -/obj/item/areaeditor/blueprints/attack_self(mob/user) +/obj/item/blueprints/dropped(mob/user) . = ..() - if(!legend) - var/area/A = get_area(user) - if(get_area_type() == AREA_STATION) - . += "

According to \the [src], you are now in \"[html_encode(A.name)]\".

" - . += "

Change area name

" - . += "

View wire colour legend

" - if(!viewing) - . += "

View structural data

" - else - . += "

Refresh structural data

" - . += "

Hide structural data

" - else - if(legend == TRUE) - . += "<< Back" - . += view_wire_devices(user); - else - //legend is a wireset - . += "<< Back" - . += view_wire_set(user, legend) - var/datum/browser/popup = new(user, "blueprints", "[src]", 700, 500) - popup.set_content(.) - popup.open() - onclose(user, "blueprints") + clear_viewer() + legend_viewing = LEGEND_OFF +/obj/item/blueprints/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Blueprints", name) + ui.open() -/obj/item/areaeditor/blueprints/Topic(href, href_list) - if(..()) +/obj/item/blueprints/ui_state(mob/user) + return GLOB.inventory_state + +/obj/item/blueprints/ui_data(mob/user) + var/list/data = list() + switch(get_area_type(user)) + if(AREA_OUTDOORS) + data["area_notice"] = "You are in unclaimed territory." + if(AREA_SPECIAL) + data["area_notice"] = "This area has no notes." + else + var/area/current_area = get_area(user) + data["area_notice"] = "You are now in \the [current_area.name]" + var/area/area_inside_of = get_area(user) + data["area_name"] = html_encode(area_inside_of.name) + data["legend"] = legend_viewing + data["viewing"] = !!viewing + data["wire_data"] = list() + if(legend_viewing != LEGEND_VIEWING_LIST && legend_viewing != LEGEND_OFF) + for(var/device in GLOB.wire_color_directory) + if("[device]" != legend_viewing) + continue + data["wires_name"] = GLOB.wire_name_directory[device] + for(var/individual_color in GLOB.wire_color_directory[device]) + var/wire_name = GLOB.wire_color_directory[device][individual_color] + if(findtext(wire_name, WIRE_DUD_PREFIX)) //don't show duds + continue + data["wire_data"] += list(list( + "color" = individual_color, + "message" = wire_name, + )) + return data + +/obj/item/blueprints/ui_static_data(mob/user) + var/list/data = list() + data["legend_viewing_list"] = LEGEND_VIEWING_LIST + data["legend_off"] = LEGEND_OFF + data["fluff_notice"] = fluffnotice + data["station_name"] = station_name() + data["wire_devices"] = list() + for(var/wireset in GLOB.wire_color_directory) + data["wire_devices"] += list(list( + "name" = GLOB.wire_name_directory[wireset], + "ref" = wireset, + )) + return data + +/obj/item/blueprints/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) return - if(href_list["edit_area"]) - if(get_area_type() != AREA_STATION) - return - if(in_use) - return - in_use = TRUE - edit_area() - in_use = FALSE - if(href_list["exit_legend"]) - legend = FALSE; - if(href_list["view_legend"]) - legend = TRUE; - if(href_list["view_wireset"]) - legend = href_list["view_wireset"]; - if(href_list["view_blueprints"]) - set_viewer(usr, span_notice("You flip the blueprints over to view the complex information diagram.")) - if(href_list["hide_blueprints"]) - clear_viewer(usr,span_notice("You flip the blueprints over to view the simple information diagram.")) - if(href_list["refresh"]) - clear_viewer(usr) - set_viewer(usr) - attack_self(usr) //this is not the proper way, but neither of the old update procs work! it's too ancient and I'm tired shush. + var/mob/user = ui.user + if(!user.can_perform_action(src, NEED_LITERACY|NEED_DEXTERITY|NEED_HANDS|ALLOW_RESTING)) + return TRUE -/obj/item/areaeditor/blueprints/proc/get_images(turf/central_turf, viewsize) - . = list() - var/list/dimensions = getviewsize(viewsize) - var/horizontal_radius = dimensions[1] / 2 - var/vertical_radius = dimensions[2] / 2 - for(var/turf/nearby_turf as anything in RECT_TURFS(horizontal_radius, vertical_radius, central_turf)) - if(nearby_turf.blueprint_data) - . += nearby_turf.blueprint_data - -/obj/item/areaeditor/blueprints/proc/set_viewer(mob/user, message = "") - if(user?.client) - if(viewing) + switch(action) + if("create_area") + if(in_use) + return + in_use = TRUE + create_area(user, new_area_type) + in_use = FALSE + if("edit_area") + if(get_area_type(user) != AREA_STATION) + return + if(in_use) + return + in_use = TRUE + edit_area(user) + in_use = FALSE + if("exit_legend") + legend_viewing = LEGEND_OFF + if("view_legend") + legend_viewing = LEGEND_VIEWING_LIST + if("view_wireset") + var/setting_wireset = params["view_wireset"] + for(var/device in GLOB.wire_color_directory) + if("[device]" == setting_wireset) //I know... don't change it... + legend_viewing = setting_wireset + return TRUE + if("view_blueprints") + playsound(src, 'sound/items/paper_flip.ogg', 40, TRUE) + user.balloon_alert_to_viewers("flips blueprints over") + set_viewer(user) + if("hide_blueprints") + playsound(src, 'sound/items/paper_flip.ogg', 40, TRUE) + user.balloon_alert_to_viewers("flips blueprints over") clear_viewer() - viewing = user.client - showing = get_images(get_turf(viewing.eye || user), viewing.view) - viewing.images |= showing - if(message) - to_chat(user, message) + if("refresh") + playsound(src, 'sound/items/paper_flip.ogg', 40, TRUE) + clear_viewer() + set_viewer(user) + return TRUE -/obj/item/areaeditor/blueprints/proc/clear_viewer(mob/user, message = "") +/** + * Sets the user's client as the person viewing blueprint data, and builds blueprint data + * around the user. + * Args: + * - user: The person who's client we're giving images to. + */ +/obj/item/blueprints/proc/set_viewer(mob/user) + if(!user || !user.client) + return + if(viewing) + clear_viewer() + viewing = user.client + showing = get_blueprint_data(get_turf(viewing.eye || user), viewing.view) + viewing.images |= showing + +/** + * Clears the client we're showig images to and deletes the images of blueprint data + * we made to show them. + */ +/obj/item/blueprints/proc/clear_viewer() if(viewing) viewing.images -= showing viewing = null showing.Cut() - if(message) - to_chat(user, message) -/obj/item/areaeditor/blueprints/dropped(mob/user) - ..() - clear_viewer() - legend = FALSE - - -/obj/item/areaeditor/proc/get_area_type(area/A) - if (!A) - A = get_area(usr) - if(A.outdoors) - return AREA_SPACE - var/list/SPECIALS = list( +/** + * Gets the area type the user is currently standing in. + * Returns: AREA_STATION, AREA_OUTDOORS, or AREA_SPECIAL + * Args: + * - user: The person we're getting the area of to check if it's a special area. + */ +/obj/item/blueprints/proc/get_area_type(mob/user) + var/area/area_checking = get_area(user) + if(area_checking.outdoors) + return AREA_OUTDOORS + var/static/list/special_areas = typecacheof(list( /area/shuttle, /area/centcom, /area/centcom/asteroid, /area/centcom/tdome, /area/centcom/wizard_station, /area/misc/hilbertshotel, - /area/misc/hilbertshotelstorage - ) - for (var/type in SPECIALS) - if ( istype(A,type) ) - return AREA_SPECIAL + /area/misc/hilbertshotelstorage, + )) + if(area_checking.type in special_areas) + return AREA_SPECIAL return AREA_STATION -/obj/item/areaeditor/blueprints/proc/view_wire_devices(mob/user) - var/message = "
You examine the wire legend.
" - for(var/wireset in GLOB.wire_color_directory) - message += "
[GLOB.wire_name_directory[wireset]]" - message += "

" - return message - -/obj/item/areaeditor/blueprints/proc/view_wire_set(mob/user, wireset) - //for some reason you can't use wireset directly as a derefencer so this is the next best :/ - for(var/device in GLOB.wire_color_directory) - if("[device]" == wireset) //I know... don't change it... - var/message = "

[GLOB.wire_name_directory[device]]:" - for(var/Col in GLOB.wire_color_directory[device]) - var/wire_name = GLOB.wire_color_directory[device][Col] - if(!findtext(wire_name, WIRE_DUD_PREFIX)) //don't show duds - message += "

[Col]: [wire_name]

" - message += "

" - return message - return "" - -/obj/item/areaeditor/proc/edit_area() - var/area/A = get_area(usr) - var/prevname = "[A.name]" - var/str = tgui_input_text(usr, "New area name", "Area Creation", max_length = MAX_NAME_LEN) - if(!str || !length(str) || str == prevname) //cancel - return - if(length(str) > 50) - to_chat(usr, span_warning("The given name is too long. The area's name is unchanged.")) +/** + * edit_area + * Takes input from the player and renames the area the blueprints are currently in. + */ +/obj/item/blueprints/proc/edit_area(mob/user) + var/area/area_editing = get_area(src) + var/prevname = "[area_editing.name]" + var/new_name = tgui_input_text(user, "New area name", "Area Creation", max_length = MAX_NAME_LEN) + if(isnull(new_name) || !length(new_name) || new_name == prevname) return - rename_area(A, str) - - to_chat(usr, span_notice("You rename the '[prevname]' to '[str]'.")) - usr.log_message("has renamed [prevname] to [str]", LOG_GAME) - A.update_areasize() - interact() + rename_area(area_editing, new_name) + user.balloon_alert(user, "area renamed to [new_name]") + user.log_message("has renamed [prevname] to [new_name]", LOG_GAME) return TRUE -//Blueprint Subtypes - -/obj/item/areaeditor/blueprints/cyborg +///Cyborg blueprints - The same as regular but with a different fluff text. +/obj/item/blueprints/cyborg name = "station schematics" desc = "A digital copy of the station blueprints stored in your memory." - icon = 'icons/obj/scrolls.dmi' - icon_state = "blueprints" fluffnotice = "Intellectual Property of Nanotrasen. For use in engineering cyborgs only. Wipe from memory upon departure from the station." -/obj/item/areaeditor/blueprints/golem +///Golem blueprints - Used to make golem areas that won't give the hazardous area debuffs. +/obj/item/blueprints/golem name = "land claim" desc = "Use it to build new structures in the wastes." fluffnotice = "In memory of the Liberator's brother, Delaminator, and his Scarlet Macaw-iathan, from which this artifact was stolen." new_area_type = /area/golem -/proc/rename_area(a, new_name) - var/area/A = get_area(a) - var/prevname = "[A.name]" - set_area_machinery_title(A, new_name, prevname) - A.name = new_name - require_area_resort() //area renamed so resort the names +///Slime blueprints - Makes areas colored and compatible with xenobiology camera consoles, one time use. +/obj/item/blueprints/slime + name = "cerulean prints" + desc = "A one use yet of blueprints made of jelly like organic material. Extends the reach of the management console." + fluffnotice = "Copyright by Science Inc. Renaming areas will allow for management consoles to traverse them." + color = "#2956B2" - if(A.firedoors) - for(var/D in A.firedoors) - var/obj/machinery/door/firedoor/FD = D - FD.CalculateAffectingAreas() - A.update_areasize() - return TRUE +/obj/item/blueprints/slime/edit_area(mob/user) + . = ..() + var/area/area = get_area(src) + for(var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + area_turf.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) + area_turf.add_atom_colour("#2956B2", FIXED_COLOUR_PRIORITY) + area.area_flags |= XENOBIOLOGY_COMPATIBLE + qdel(src) +#undef LEGEND_VIEWING_LIST +#undef LEGEND_OFF -/proc/set_area_machinery_title(area/area, title, oldtitle) - if(!oldtitle) // or replacetext goes to infinite loop - return +#undef AREA_STATION +#undef AREA_OUTDOORS +#undef AREA_SPECIAL - //stuff tied to the area to rename - var/static/list/to_rename = typecacheof(list( - /obj/machinery/airalarm, - /obj/machinery/atmospherics/components/unary/vent_scrubber, - /obj/machinery/atmospherics/components/unary/vent_pump, - /obj/machinery/door, - /obj/machinery/firealarm, - /obj/machinery/light_switch, - /obj/machinery/power/apc, - )) - for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) - for (var/turf/area_turf as anything in zlevel_turfs) - for(var/obj/machine as anything in typecache_filter_list(area_turf.contents, to_rename)) - machine.name = replacetext(machine.name, oldtitle, title) - //TODO: much much more. Unnamed airlocks, cameras, etc. diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index 8c9ef30687a..0d8874099e8 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -671,44 +671,45 @@ to_chat(user, span_notice("The provided account has been linked to this ID card. It contains [account.account_balance] credits.")) return TRUE -/obj/item/card/id/AltClick(mob/living/user) +/obj/item/card/id/click_alt(mob/living/user) if(!alt_click_can_use_id(user)) - return + return NONE if(registered_account.account_debt) var/choice = tgui_alert(user, "Choose An Action", "Bank Account", list("Withdraw", "Pay Debt")) if(!choice || QDELETED(user) || QDELETED(src) || !alt_click_can_use_id(user) || loc != user) - return + return CLICK_ACTION_BLOCKING if(choice == "Pay Debt") pay_debt(user) - return + return CLICK_ACTION_SUCCESS if (registered_account.being_dumped) registered_account.bank_card_talk(span_warning("内部服务器错误"), TRUE) - return + return CLICK_ACTION_SUCCESS if(loc != user) to_chat(user, span_warning("You must be holding the ID to continue!")) - return + return CLICK_ACTION_BLOCKING if(registered_account.replaceable && !registered_account.account_balance) var/choice = tgui_alert(user, "This card's account is unassigned. Would you like to link a bank account?", "Bank Account", list("Link Account", "Leave Unassigned")) if(!choice || QDELETED(user) || QDELETED(src) || !alt_click_can_use_id(user) || loc != user) - return + return CLICK_ACTION_BLOCKING if(choice == "Link Account") set_new_account(user) - return + return CLICK_ACTION_SUCCESS var/amount_to_remove = tgui_input_number(user, "How much do you want to withdraw? (Max: [registered_account.account_balance] cr)", "Withdraw Funds", max_value = registered_account.account_balance) if(!amount_to_remove || QDELETED(user) || QDELETED(src) || issilicon(user) || loc != user) - return + return CLICK_ACTION_BLOCKING if(!alt_click_can_use_id(user)) - return + return CLICK_ACTION_BLOCKING if(registered_account.adjust_money(-amount_to_remove, "System: Withdrawal")) var/obj/item/holochip/holochip = new (user.drop_location(), amount_to_remove) user.put_in_hands(holochip) to_chat(user, span_notice("You withdraw [amount_to_remove] credits into a holochip.")) SSblackbox.record_feedback("amount", "credits_removed", amount_to_remove) log_econ("[amount_to_remove] credits were removed from [src] owned by [src.registered_name]") - return + return CLICK_ACTION_SUCCESS else var/difference = amount_to_remove - registered_account.account_balance registered_account.bank_card_talk(span_warning("ERROR: The linked account requires [difference] more credit\s to perform that withdrawal."), TRUE) + return CLICK_ACTION_BLOCKING /obj/item/card/id/alt_click_secondary(mob/user) . = ..() @@ -923,8 +924,9 @@ department_name = ACCOUNT_CAR_NAME icon_state = "car_budget" //saving up for a new tesla -/obj/item/card/id/departmental_budget/AltClick(mob/living/user) +/obj/item/card/id/departmental_budget/click_alt(mob/living/user) registered_account.bank_card_talk(span_warning("Withdrawing is not compatible with this card design."), TRUE) //prevents the vault bank machine being useless and putting money from the budget to your card to go over personal crates + return CLICK_ACTION_BLOCKING /obj/item/card/id/advanced name = "identification card" diff --git a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm index 8d6c240ed0d..faf7c76e502 100644 --- a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm @@ -1236,11 +1236,10 @@ suction = !suction to_chat(user, span_notice("You [suction ? "enable" : "disable"] the board's suction function.")) -/obj/item/circuitboard/machine/dish_drive/AltClick(mob/living/user) - if(!user.Adjacent(src)) - return +/obj/item/circuitboard/machine/dish_drive/click_alt(mob/living/user) transmit = !transmit to_chat(user, span_notice("You [transmit ? "enable" : "disable"] the board's automatic disposal transmission.")) + return CLICK_ACTION_SUCCESS /obj/item/circuitboard/machine/gibber name = "Gibber" diff --git a/code/game/objects/items/cosmetics.dm b/code/game/objects/items/cosmetics.dm index bbb5e9e177d..42402c88e10 100644 --- a/code/game/objects/items/cosmetics.dm +++ b/code/game/objects/items/cosmetics.dm @@ -10,6 +10,7 @@ icon_state = "lipstick" inhand_icon_state = "lipstick" w_class = WEIGHT_CLASS_TINY + interaction_flags_click = NEED_DEXTERITY|NEED_HANDS|ALLOW_RESTING var/open = FALSE /// Actual color of the lipstick, also gets applied to the human var/lipstick_color = COLOR_RED @@ -45,15 +46,9 @@ colored_overlay.color = lipstick_color . += colored_overlay -/obj/item/lipstick/AltClick(mob/user) - . = ..() - if(.) - return TRUE - - if(!user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS|ALLOW_RESTING)) - return FALSE - - return display_radial_menu(user) +/obj/item/lipstick/click_alt(mob/user) + display_radial_menu(user) + return CLICK_ACTION_SUCCESS /obj/item/lipstick/proc/display_radial_menu(mob/living/carbon/human/user) var/style_options = list( diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index c3eca2eb033..4cb077808a8 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -418,7 +418,7 @@ /obj/item/toy/crayon/proc/crayon_text_strip(text) text = copytext(text, 1, MAX_MESSAGE_LEN) var/static/regex/crayon_regex = new /regex(@"[^\w!?,.=&%#+/\-]", "ig") - return lowertext(crayon_regex.Replace(text, "")) + return LOWER_TEXT(crayon_regex.Replace(text, "")) /// Attempts to color the target. Returns how many charges were used. /obj/item/toy/crayon/proc/use_on(atom/target, mob/user, params) @@ -759,6 +759,7 @@ pre_noise = TRUE post_noise = FALSE + interaction_flags_click = NEED_DEXTERITY|NEED_HANDS /obj/item/toy/crayon/spraycan/Initialize(mapload) . = ..() @@ -960,12 +961,13 @@ return SECONDARY_ATTACK_CONTINUE_CHAIN -/obj/item/toy/crayon/spraycan/AltClick(mob/user) - if(!has_cap || !user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS)) - return +/obj/item/toy/crayon/spraycan/click_alt(mob/user) + if(!has_cap) + return CLICK_ACTION_BLOCKING is_capped = !is_capped balloon_alert(user, is_capped ? "capped" : "cap removed") update_appearance() + return CLICK_ACTION_SUCCESS /obj/item/toy/crayon/spraycan/attackby_storage_insert(datum/storage, atom/storage_holder, mob/user) return is_capped diff --git a/code/game/objects/items/credit_holochip.dm b/code/game/objects/items/credit_holochip.dm index 83e6165b91d..c9b6fe4a134 100644 --- a/code/game/objects/items/credit_holochip.dm +++ b/code/game/objects/items/credit_holochip.dm @@ -7,6 +7,8 @@ throwforce = 0 force = 0 w_class = WEIGHT_CLASS_TINY + interaction_flags_click = NEED_DEXTERITY|FORBID_TELEKINESIS_REACH + /// Amount on money on the card var/credits = 0 /obj/item/holochip/Initialize(mapload, amount = 1) @@ -101,23 +103,21 @@ update_appearance() qdel(H) -/obj/item/holochip/AltClick(mob/user) - if(!user.can_perform_action(src, NEED_DEXTERITY|FORBID_TELEKINESIS_REACH)) - return +/obj/item/holochip/click_alt(mob/user) if(loc != user) to_chat(user, span_warning("You must be holding the holochip to continue!")) - return FALSE + return CLICK_ACTION_BLOCKING var/split_amount = tgui_input_number(user, "How many credits do you want to extract from the holochip? (Max: [credits] cr)", "Holochip", max_value = credits) if(!split_amount || QDELETED(user) || QDELETED(src) || issilicon(user) || !usr.can_perform_action(src, NEED_DEXTERITY|FORBID_TELEKINESIS_REACH) || loc != user) - return + return CLICK_ACTION_BLOCKING var/new_credits = spend(split_amount, TRUE) - var/obj/item/holochip/H = new(user ? user : drop_location(), new_credits) + var/obj/item/holochip/chip = new(user ? user : drop_location(), new_credits) if(user) - if(!user.put_in_hands(H)) - H.forceMove(user.drop_location()) + if(!user.put_in_hands(chip)) + chip.forceMove(user.drop_location()) add_fingerprint(user) - H.add_fingerprint(user) to_chat(user, span_notice("You extract [split_amount] credits into a new holochip.")) + return CLICK_ACTION_SUCCESS /obj/item/holochip/emp_act(severity) . = ..() diff --git a/code/game/objects/items/devices/anomaly_releaser.dm b/code/game/objects/items/devices/anomaly_releaser.dm index a32220685ec..0556b2a2afd 100644 --- a/code/game/objects/items/devices/anomaly_releaser.dm +++ b/code/game/objects/items/devices/anomaly_releaser.dm @@ -28,6 +28,9 @@ if(!do_after(user, 3 SECONDS, target)) return + if(used) + return + var/obj/item/assembly/signaler/anomaly/core = target if(!core.anomaly_type) @@ -35,6 +38,7 @@ var/obj/effect/anomaly/anomaly = new core.anomaly_type(get_turf(core)) anomaly.stabilize() + log_combat(user, anomaly, "released", object = src, addition = "in [get_area(target)].") if(infinite) return diff --git a/code/game/objects/items/devices/desynchronizer.dm b/code/game/objects/items/devices/desynchronizer.dm index 7a2efbcec7e..b7b693b999f 100644 --- a/code/game/objects/items/devices/desynchronizer.dm +++ b/code/game/objects/items/devices/desynchronizer.dm @@ -9,11 +9,18 @@ lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi' righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi' custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 2.5, /datum/material/glass= SMALL_MATERIAL_AMOUNT * 5) - var/max_duration = 3000 - var/duration = 300 + interaction_flags_click = NEED_DEXTERITY + /// Max time this can be set + var/max_duration = 300 SECONDS + /// Currently set time + var/duration = 30 SECONDS + /// Last world time var/last_use = 0 + /// world.time + (world.time - last_use) var/next_use = 0 + /// The current space time rift var/obj/effect/abstract/sync_holder/sync_holder + /// Timer obj for calling resync var/resync_timer /obj/item/desynchronizer/attack_self(mob/living/user) @@ -32,14 +39,13 @@ . += span_notice("Alt-click to customize the duration. Current duration: [DisplayTimeText(duration)].") . += span_notice("Can be used again to interrupt the effect early. The recharge time is the same as the time spent in desync.") -/obj/item/desynchronizer/AltClick(mob/living/user) - if(!user.can_perform_action(src, NEED_DEXTERITY)) - return +/obj/item/desynchronizer/click_alt(mob/living/user) var/new_duration = tgui_input_number(user, "Set the duration", "Desynchronizer", duration / 10, max_duration, 5) if(!new_duration || QDELETED(user) || QDELETED(src) || !usr.can_perform_action(src, NEED_DEXTERITY)) - return + return CLICK_ACTION_BLOCKING duration = new_duration to_chat(user, span_notice("You set the duration to [DisplayTimeText(duration)].")) + return CLICK_ACTION_SUCCESS /obj/item/desynchronizer/proc/desync(mob/living/user) if(sync_holder) diff --git a/code/game/objects/items/devices/geiger_counter.dm b/code/game/objects/items/devices/geiger_counter.dm index 6e152c33661..db2d0d820ba 100644 --- a/code/game/objects/items/devices/geiger_counter.dm +++ b/code/game/objects/items/devices/geiger_counter.dm @@ -110,12 +110,11 @@ to_chat(user, span_notice("[icon2html(src, user)] [isliving(target) ? "Subject" : "Target"] is free of radioactive contamination.")) -/obj/item/geiger_counter/AltClick(mob/living/user) - if(!istype(user) || !user.can_perform_action(src)) - return ..() +/obj/item/geiger_counter/click_alt(mob/living/user) if(!scanning) to_chat(usr, span_warning("[src] must be on to reset its radiation level!")) - return + return CLICK_ACTION_BLOCKING to_chat(usr, span_notice("You flush [src]'s radiation counts, resetting it to normal.")) last_perceived_radiation_danger = null update_appearance(UPDATE_ICON) + return CLICK_ACTION_SUCCESS diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index 026e560cc97..225e914fbf6 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -80,14 +80,11 @@ diode = null return TRUE -/obj/item/laser_pointer/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) - . = ..() - if(. & ITEM_INTERACT_ANY_BLOCKER) - return . +/obj/item/laser_pointer/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(isnull(crystal_lens)) - return . + return NONE if(tool_behaviour != TOOL_WIRECUTTER && tool_behaviour != TOOL_HEMOSTAT) - return . + return NONE tool.play_tool_sound(src) balloon_alert(user, "removed crystal lens") crystal_lens.forceMove(drop_location()) diff --git a/code/game/objects/items/devices/quantum_keycard.dm b/code/game/objects/items/devices/quantum_keycard.dm index abffdcca4d5..34b83a62092 100644 --- a/code/game/objects/items/devices/quantum_keycard.dm +++ b/code/game/objects/items/devices/quantum_keycard.dm @@ -10,6 +10,8 @@ righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi' w_class = WEIGHT_CLASS_TINY obj_flags = UNIQUE_RENAME + interaction_flags_click = NEED_DEXTERITY + /// The linked quantum pad var/obj/machinery/quantumpad/qpad /// where the pad is located and what color the card will become @@ -40,13 +42,12 @@ else . += span_notice("Insert [src] into an active quantum pad to link it.") -/obj/item/quantum_keycard/AltClick(mob/living/user) - if(!istype(user) || !user.can_perform_action(src, NEED_DEXTERITY)) - return +/obj/item/quantum_keycard/click_alt(mob/living/user) to_chat(user, span_notice("You start pressing [src]'s unlink button...")) if(do_after(user, 4 SECONDS, target = src)) to_chat(user, span_notice("The keycard beeps twice and disconnects the quantum link.")) set_pad() + return CLICK_ACTION_SUCCESS /obj/item/quantum_keycard/proc/set_pad(obj/machinery/quantumpad/new_pad) qpad = new_pad diff --git a/code/game/objects/items/devices/radio/encryptionkey.dm b/code/game/objects/items/devices/radio/encryptionkey.dm index b7a96d777ef..88c9251d5b2 100644 --- a/code/game/objects/items/devices/radio/encryptionkey.dm +++ b/code/game/objects/items/devices/radio/encryptionkey.dm @@ -21,7 +21,7 @@ if(LAZYLEN(channels) || translate_binary) var/list/examine_text_list = list() for(var/i in channels) - examine_text_list += "[GLOB.channel_tokens[i]] - [lowertext(i)]" + examine_text_list += "[GLOB.channel_tokens[i]] - [LOWER_TEXT(i)]" if(translate_binary) examine_text_list += "[GLOB.channel_tokens[MODE_BINARY]] - [MODE_BINARY]" diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index fff7b0a655a..b9f2090eeb4 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -60,9 +60,9 @@ GLOBAL_LIST_INIT(channel_tokens, list( if(length(channels)) for(var/i in 1 to length(channels)) if(i == 1) - avail_chans += "use [MODE_TOKEN_DEPARTMENT] or [GLOB.channel_tokens[channels[i]]] for [lowertext(channels[i])]" + avail_chans += "use [MODE_TOKEN_DEPARTMENT] or [GLOB.channel_tokens[channels[i]]] for [LOWER_TEXT(channels[i])]" else - avail_chans += "use [GLOB.channel_tokens[channels[i]]] for [lowertext(channels[i])]" + avail_chans += "use [GLOB.channel_tokens[channels[i]]] for [LOWER_TEXT(channels[i])]" . += span_notice("A small screen on the headset displays the following available frequencies:\n[english_list(avail_chans)].") if(command) @@ -453,9 +453,9 @@ GLOBAL_LIST_INIT(channel_tokens, list( // And grant all the languages we definitely should know now grant_headset_languages(mob_loc) -/obj/item/radio/headset/AltClick(mob/living/user) - if(!istype(user) || !Adjacent(user) || user.incapacitated()) - return - if (command) - use_command = !use_command - to_chat(user, span_notice("You toggle high-volume mode [use_command ? "on" : "off"].")) +/obj/item/radio/headset/click_alt(mob/living/user) + if (!command) + return CLICK_ACTION_BLOCKING + use_command = !use_command + to_chat(user, span_notice("You toggle high-volume mode [use_command ? "on" : "off"].")) + return CLICK_ACTION_SUCCESS diff --git a/code/game/objects/items/devices/scanners/autopsy_scanner.dm b/code/game/objects/items/devices/scanners/autopsy_scanner.dm index 16f90489b20..c5d33b74226 100644 --- a/code/game/objects/items/devices/scanners/autopsy_scanner.dm +++ b/code/game/objects/items/devices/scanners/autopsy_scanner.dm @@ -13,7 +13,7 @@ custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT*2) custom_price = PAYCHECK_COMMAND -/obj/item/autopsy_scanner/interact_with_atom(atom/interacting_with, mob/living/user) +/obj/item/autopsy_scanner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!isliving(interacting_with)) return NONE if(!user.can_read(src) || user.is_blind()) diff --git a/code/game/objects/items/devices/scanners/gas_analyzer.dm b/code/game/objects/items/devices/scanners/gas_analyzer.dm index 2b4d09fb308..0898c73aa2e 100644 --- a/code/game/objects/items/devices/scanners/gas_analyzer.dm +++ b/code/game/objects/items/devices/scanners/gas_analyzer.dm @@ -17,10 +17,16 @@ tool_behaviour = TOOL_ANALYZER custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT * 0.3, /datum/material/glass=SMALL_MATERIAL_AMOUNT * 0.2) grind_results = list(/datum/reagent/mercury = 5, /datum/reagent/iron = 5, /datum/reagent/silicon = 5) + interaction_flags_click = NEED_LITERACY|NEED_LIGHT + /// Boolean whether this has a CD var/cooldown = FALSE - var/cooldown_time = 250 - var/barometer_accuracy // 0 is the best accuracy. + /// The time in deciseconds + var/cooldown_time = 25 SECONDS + /// 0 is best accuracy + var/barometer_accuracy + /// Cached gasmix data from ui_interact var/list/last_gasmix_data + /// Max scan distance var/ranged_scan_distance = 1 /obj/item/analyzer/Initialize(mapload) @@ -53,19 +59,14 @@ user.visible_message(span_suicide("[user] begins to analyze [user.p_them()]self with [src]! The display shows that [user.p_theyre()] dead!")) return BRUTELOSS -/obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens - ..() - - if(!user.can_perform_action(src, NEED_LITERACY|NEED_LIGHT)) - return - +/obj/item/analyzer/click_alt(mob/user) //Barometer output for measuring when the next storm happens if(cooldown) to_chat(user, span_warning("[src]'s barometer function is preparing itself.")) - return + return CLICK_ACTION_BLOCKING var/turf/T = get_turf(user) if(!T) - return + return CLICK_ACTION_BLOCKING playsound(src, 'sound/effects/pop.ogg', 100) var/area/user_area = T.loc @@ -73,7 +74,7 @@ if(!user_area.outdoors) to_chat(user, span_warning("[src]'s barometer function won't work indoors!")) - return + return CLICK_ACTION_BLOCKING for(var/V in SSweather.processing) var/datum/weather/W = V @@ -84,7 +85,7 @@ if(ongoing_weather) if((ongoing_weather.stage == MAIN_STAGE) || (ongoing_weather.stage == WIND_DOWN_STAGE)) to_chat(user, span_warning("[src]'s barometer function can't trace anything while the storm is [ongoing_weather.stage == MAIN_STAGE ? "already here!" : "winding down."]")) - return + return CLICK_ACTION_BLOCKING to_chat(user, span_notice("The next [ongoing_weather] will hit in [butchertime(ongoing_weather.next_hit_time - world.time)].")) if(ongoing_weather.aesthetic) @@ -98,6 +99,7 @@ to_chat(user, span_warning("[src]'s barometer function says a storm will land in approximately [butchertime(fixed)].")) cooldown = TRUE addtimer(CALLBACK(src, TYPE_PROC_REF(/obj/item/analyzer, ping)), cooldown_time) + return CLICK_ACTION_SUCCESS /obj/item/analyzer/proc/ping() if(isliving(loc)) @@ -159,7 +161,7 @@ var/list/airs = islist(mixture) ? mixture : list(mixture) var/list/new_gasmix_data = list() for(var/datum/gas_mixture/air as anything in airs) - var/mix_name = capitalize(lowertext(target.name)) + var/mix_name = capitalize(LOWER_TEXT(target.name)) if(airs.len != 1) //not a unary gas mixture mix_name += " - Node [airs.Find(air)]" new_gasmix_data += list(gas_mixture_parser(air, mix_name)) @@ -184,7 +186,7 @@ var/list/airs = islist(mixture) ? mixture : list(mixture) for(var/datum/gas_mixture/air as anything in airs) - var/mix_name = capitalize(lowertext(target.name)) + var/mix_name = capitalize(LOWER_TEXT(target.name)) if(airs.len > 1) //not a unary gas mixture var/mix_number = airs.Find(air) message += span_boldnotice("Node [mix_number]") diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm index 0e9e4f193bc..2d8912fb242 100644 --- a/code/game/objects/items/devices/scanners/health_analyzer.dm +++ b/code/game/objects/items/devices/scanners/health_analyzer.dm @@ -20,8 +20,12 @@ throw_speed = 3 throw_range = 7 custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT *2) + interaction_flags_click = NEED_LITERACY|NEED_LIGHT + /// Verbose/condensed var/mode = SCANNER_VERBOSE + /// HEALTH/WOUND var/scanmode = SCANMODE_HEALTH + /// Advanced health analyzer var/advanced = FALSE custom_price = PAYCHECK_COMMAND /// If this analyzer will give a bonus to wound treatments apon woundscan. @@ -51,7 +55,7 @@ if(SCANMODE_WOUND) to_chat(user, span_notice("You switch the health analyzer to report extra info on wounds.")) -/obj/item/healthanalyzer/interact_with_atom(atom/interacting_with, mob/living/user) +/obj/item/healthanalyzer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!isliving(interacting_with)) return NONE if(!user.can_read(src)) //SKYRAT EDIT CHANGE - Blind People Can Analyze Again- ORIGINAL: if(!user.can_read(src) || user.is_blind()) @@ -89,7 +93,7 @@ add_fingerprint(user) -/obj/item/healthanalyzer/interact_with_atom_secondary(atom/interacting_with, mob/living/user) +/obj/item/healthanalyzer/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) if(!isliving(interacting_with)) return NONE if(!user.can_read(src)) // SKYRAT EDIT CHANGE - Blind people can analyze again - ORIGINAL: if(!user.can_read(src) || user.is_blind()) @@ -500,17 +504,13 @@ // we handled the last
so we don't need handholding to_chat(user, examine_block(jointext(render_list, "")), trailing_newline = FALSE, type = MESSAGE_TYPE_INFO) -/obj/item/healthanalyzer/AltClick(mob/user) - ..() - - if(!user.can_perform_action(src, NEED_LITERACY|NEED_LIGHT) || user.is_blind()) - return - +/obj/item/healthanalyzer/click_alt(mob/user) if(mode == SCANNER_NO_MODE) - return + return CLICK_ACTION_BLOCKING mode = !mode to_chat(user, mode == SCANNER_VERBOSE ? "The scanner now shows specific limb damage." : "The scanner no longer shows limb damage.") + return CLICK_ACTION_SUCCESS /obj/item/healthanalyzer/advanced name = "advanced health analyzer" @@ -607,7 +607,7 @@ /obj/item/healthanalyzer/simple/proc/violence_damage(mob/living/user) user.adjustBruteLoss(4) -/obj/item/healthanalyzer/simple/interact_with_atom(atom/interacting_with, mob/living/user) +/obj/item/healthanalyzer/simple/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!isliving(interacting_with)) return NONE if(!user.can_read(src)) //SKYRAT EDIT CHANGE - Blind People Can Analyze Again - ORIGINAL: if(!user.can_read(src) || user.is_blind()) diff --git a/code/game/objects/items/devices/scanners/sequence_scanner.dm b/code/game/objects/items/devices/scanners/sequence_scanner.dm index 3d212cbb771..3a45dae813b 100644 --- a/code/game/objects/items/devices/scanners/sequence_scanner.dm +++ b/code/game/objects/items/devices/scanners/sequence_scanner.dm @@ -29,7 +29,7 @@ if(LAZYLEN(genetic_makeup_buffer) > 0) . += span_notice("It has the genetic makeup of \"[genetic_makeup_buffer["name"]]\" stored inside its buffer") -/obj/item/sequence_scanner/interact_with_atom(atom/interacting_with, mob/living/user) +/obj/item/sequence_scanner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!isliving(interacting_with)) return NONE @@ -46,7 +46,7 @@ user.visible_message(span_notice("[user] fails to analyze [interacting_with]'s genetic sequence."), span_warning("[interacting_with] has no readable genetic sequence!")) return ITEM_INTERACT_BLOCKING -/obj/item/sequence_scanner/interact_with_atom_secondary(atom/interacting_with, mob/living/user) +/obj/item/sequence_scanner/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) if(!isliving(interacting_with)) return NONE diff --git a/code/game/objects/items/devices/scanners/slime_scanner.dm b/code/game/objects/items/devices/scanners/slime_scanner.dm index ee8567ac6cc..bf55265f783 100644 --- a/code/game/objects/items/devices/scanners/slime_scanner.dm +++ b/code/game/objects/items/devices/scanners/slime_scanner.dm @@ -13,7 +13,7 @@ throw_range = 7 custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT*0.30, /datum/material/glass=SMALL_MATERIAL_AMOUNT * 0.20) -/obj/item/slime_scanner/interact_with_atom(atom/interacting_with, mob/living/user) +/obj/item/slime_scanner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!isliving(interacting_with)) return NONE if(!user.can_read(src)) //SKYRAT EDIT CHANGE - Blind People Can Analyze Again - ORIGINAL : if(!user.can_read(src) || user.is_blind()) diff --git a/code/game/objects/items/devices/swapper.dm b/code/game/objects/items/devices/swapper.dm index e7a749fc978..6db67049174 100644 --- a/code/game/objects/items/devices/swapper.dm +++ b/code/game/objects/items/devices/swapper.dm @@ -8,9 +8,12 @@ item_flags = NOBLUDGEON lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi' righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi' - - var/cooldown = 300 + interaction_flags_click = NEED_DEXTERITY + /// Cooldown for usage + var/cooldown = 30 SECONDS + /// Next available time var/next_use = 0 + /// Swapper linked to this obj var/obj/item/swapper/linked_swapper /obj/item/swapper/Destroy() @@ -72,15 +75,14 @@ else . += span_notice("Not Linked. Use on another quantum spin inverter to establish a quantum link.") -/obj/item/swapper/AltClick(mob/living/user) - if(!user.can_perform_action(src, NEED_DEXTERITY)) - return +/obj/item/swapper/click_alt(mob/living/user) to_chat(user, span_notice("You break the current quantum link.")) if(!QDELETED(linked_swapper)) linked_swapper.linked_swapper = null linked_swapper.update_appearance() linked_swapper = null update_appearance() + return CLICK_ACTION_SUCCESS //Gets the topmost teleportable container /obj/item/swapper/proc/get_teleportable_container() diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index c686eeb04a7..d30f379197e 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -61,11 +61,9 @@ . += span_notice("The wire panel is [open_panel ? "opened" : "closed"]. The display reads:") . += "[readout()]" -/obj/item/taperecorder/AltClick(mob/user) - . = ..() - if(!can_interact(user)) - return +/obj/item/taperecorder/click_alt(mob/user) play() + return CLICK_ACTION_SUCCESS /obj/item/taperecorder/proc/update_available_icons() icons_available = list() diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm index 8e8f2578fa4..7e6ee077fce 100644 --- a/code/game/objects/items/devices/traitordevices.dm +++ b/code/game/objects/items/devices/traitordevices.dm @@ -76,7 +76,7 @@ effective or pretty fucking useless. var/intensity = 10 // how much damage the radiation does var/wavelength = 10 // time it takes for the radiation to kick in, in seconds -/obj/item/healthanalyzer/rad_laser/interact_with_atom(atom/interacting_with, mob/living/user) +/obj/item/healthanalyzer/rad_laser/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!stealth || !irradiate) . = ..() diff --git a/code/game/objects/items/dualsaber.dm b/code/game/objects/items/dualsaber.dm index 9a08e571994..b32d01b0dfc 100644 --- a/code/game/objects/items/dualsaber.dm +++ b/code/game/objects/items/dualsaber.dm @@ -61,7 +61,7 @@ if(user.dna.check_mutation(/datum/mutation/human/hulk)) to_chat(user, span_warning("You lack the grace to wield this!")) return COMPONENT_TWOHANDED_BLOCK_WIELD - w_class = w_class_on + update_weight_class(w_class_on) hitsound = 'sound/weapons/blade1.ogg' START_PROCESSING(SSobj, src) set_light_on(TRUE) @@ -69,7 +69,7 @@ /// Triggered on unwield of two handed item /// switch hitsounds /obj/item/dualsaber/proc/on_unwield(obj/item/source, mob/living/carbon/user) - w_class = initial(w_class) + update_weight_class(initial(w_class)) hitsound = SFX_SWING_HIT STOP_PROCESSING(SSobj, src) set_light_on(FALSE) diff --git a/code/game/objects/items/emags.dm b/code/game/objects/items/emags.dm index 141e242fc03..f197a9b5fdb 100644 --- a/code/game/objects/items/emags.dm +++ b/code/game/objects/items/emags.dm @@ -49,7 +49,7 @@ user.visible_message(span_notice("[user] shows you: [icon2html(src, viewers(user))] [name]."), span_notice("You show [src].")) add_fingerprint(user) -/obj/item/card/emagfake/interact_with_atom(atom/interacting_with, mob/living/user) +/obj/item/card/emagfake/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) playsound(src, 'sound/items/bikehorn.ogg', 50, TRUE) return ITEM_INTERACT_SKIP_TO_ATTACK // So it does the attack animation. @@ -57,7 +57,7 @@ . = ..() type_blacklist = list(typesof(/obj/machinery/door/airlock) + typesof(/obj/machinery/door/window/) + typesof(/obj/machinery/door/firedoor) - typesof(/obj/machinery/door/airlock/tram)) //list of all typepaths that require a specialized emag to hack. -/obj/item/card/emag/interact_with_atom(atom/interacting_with, mob/living/user) +/obj/item/card/emag/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!can_emag(interacting_with, user)) return ITEM_INTERACT_BLOCKING log_combat(user, interacting_with, "attempted to emag") diff --git a/code/game/objects/items/etherealdiscoball.dm b/code/game/objects/items/etherealdiscoball.dm index 0a95e4bbc73..fe066bd1bf5 100644 --- a/code/game/objects/items/etherealdiscoball.dm +++ b/code/game/objects/items/etherealdiscoball.dm @@ -41,10 +41,10 @@ TurnOn() to_chat(user, span_notice("You turn the disco ball on!")) -/obj/structure/etherealball/AltClick(mob/living/carbon/human/user) - . = ..() +/obj/structure/etherealball/click_alt(mob/living/carbon/human/user) set_anchored(!anchored) to_chat(user, span_notice("You [anchored ? null : "un"]lock the disco ball.")) + return CLICK_ACTION_SUCCESS /obj/structure/etherealball/proc/TurnOn() TurnedOn = TRUE //Same diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm index 0b2daeb655d..c78242255a6 100644 --- a/code/game/objects/items/extinguisher.dm +++ b/code/game/objects/items/extinguisher.dm @@ -18,6 +18,7 @@ attack_verb_simple = list("slam", "whack", "bash", "thunk", "batter", "bludgeon", "thrash") dog_fashion = /datum/dog_fashion/back resistance_flags = FIRE_PROOF + interaction_flags_click = NEED_DEXTERITY|NEED_HANDS /// The max amount of water this extinguisher can hold. var/max_water = 50 /// Does the welder extinguisher start with water. @@ -270,13 +271,12 @@ if(1 to 3) source.delay = 3 -/obj/item/extinguisher/AltClick(mob/user) - if(!user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS)) - return +/obj/item/extinguisher/click_alt(mob/user) if(!user.is_holding(src)) to_chat(user, span_notice("You must be holding the [src] in your hands do this!")) - return + return CLICK_ACTION_BLOCKING EmptyExtinguisher(user) + return CLICK_ACTION_SUCCESS /obj/item/extinguisher/proc/EmptyExtinguisher(mob/user) if(loc == user && reagents.total_volume) diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm index 346b8597533..d2f4b0cfc71 100644 --- a/code/game/objects/items/flamethrower.dm +++ b/code/game/objects/items/flamethrower.dm @@ -20,6 +20,7 @@ light_range = 2 light_power = 2 light_on = FALSE + interaction_flags_click = NEED_DEXTERITY|NEED_HANDS var/status = FALSE var/lit = FALSE //on or off var/operating = FALSE//cooldown @@ -158,12 +159,15 @@ /obj/item/flamethrower/attack_self(mob/user) toggle_igniter(user) -/obj/item/flamethrower/AltClick(mob/user) - if(ptank && isliving(user) && user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS)) - user.put_in_hands(ptank) - ptank = null - to_chat(user, span_notice("You remove the plasma tank from [src]!")) - update_appearance() +/obj/item/flamethrower/click_alt(mob/user) + if(isnull(ptank)) + return NONE + + user.put_in_hands(ptank) + ptank = null + to_chat(user, span_notice("You remove the plasma tank from [src]!")) + update_appearance() + return CLICK_ACTION_SUCCESS /obj/item/flamethrower/examine(mob/user) . = ..() @@ -219,10 +223,6 @@ sleep(0.1 SECONDS) previousturf = T operating = FALSE - for(var/mob/M in viewers(1, loc)) - if((M.client && M.machine == src)) - attack_self(M) - /obj/item/flamethrower/proc/default_ignite(turf/target, release_amount = 0.05) //TODO: DEFERRED Consider checking to make sure tank pressure is high enough before doing this... diff --git a/code/game/objects/items/granters/magic/_spell_granter.dm b/code/game/objects/items/granters/magic/_spell_granter.dm index e1ca6352293..21a69248a14 100644 --- a/code/game/objects/items/granters/magic/_spell_granter.dm +++ b/code/game/objects/items/granters/magic/_spell_granter.dm @@ -91,4 +91,4 @@ spell_options -= spell granted_action = pick(spell_options) - action_name = lowertext(initial(granted_action.name)) + action_name = LOWER_TEXT(initial(granted_action.name)) diff --git a/code/game/objects/items/grenades/plastic.dm b/code/game/objects/items/grenades/plastic.dm index 8e8aeb2617f..c1cf8c1010d 100644 --- a/code/game/objects/items/grenades/plastic.dm +++ b/code/game/objects/items/grenades/plastic.dm @@ -12,11 +12,19 @@ display_timer = FALSE w_class = WEIGHT_CLASS_SMALL gender = PLURAL + /// What the charge is stuck to var/atom/target = null + /// C4 overlay to put on target var/mutable_appearance/plastic_overlay + /// Do we do a directional explosion when target is a a dense atom? var/directional = FALSE + /// When doing a directional explosion, what arc does the explosion cover + var/directional_arc = 120 + /// For directional charges, which cardinal direction is the charge facing? var/aim_dir = NORTH + /// List of explosion radii (DEV, HEAVY, LIGHT) var/boom_sizes = list(0, 0, 3) + /// Do we apply the full force of a heavy ex_act() to mob targets var/full_damage_on_mobs = FALSE /// Minimum timer for c4 charges var/minimum_timer = 10 @@ -68,18 +76,20 @@ . = ..() var/turf/location + var/target_density if(target) if(!QDELETED(target)) location = get_turf(target) + target_density = target.density // We're about to blow target up, so need to save this value for later target.cut_overlay(plastic_overlay, TRUE) if(!ismob(target) || full_damage_on_mobs) EX_ACT(target, EXPLODE_HEAVY, target) else location = get_turf(src) if(location) - if(directional && target?.density) - var/turf/turf = get_step(location, aim_dir) - explosion(get_step(turf, aim_dir), devastation_range = boom_sizes[1], heavy_impact_range = boom_sizes[2], light_impact_range = boom_sizes[3], explosion_cause = src) + if(directional && target_density) + var/angle = dir2angle(aim_dir) + explosion(location, devastation_range = boom_sizes[1], heavy_impact_range = boom_sizes[2], light_impact_range = boom_sizes[3], explosion_cause = src, explosion_direction = angle, explosion_arc = directional_arc) else explosion(location, devastation_range = boom_sizes[1], heavy_impact_range = boom_sizes[2], light_impact_range = boom_sizes[3], explosion_cause = src) qdel(src) diff --git a/code/game/objects/items/hand_items.dm b/code/game/objects/items/hand_items.dm index 2619a6cb65f..eb616768283 100644 --- a/code/game/objects/items/hand_items.dm +++ b/code/game/objects/items/hand_items.dm @@ -505,7 +505,7 @@ blown_kiss.original = target blown_kiss.fired_from = user blown_kiss.firer = user // don't hit ourself that would be really annoying - blown_kiss.impacted = list(user = TRUE) // just to make sure we don't hit the wearer + blown_kiss.impacted = list(WEAKREF(user) = TRUE) // just to make sure we don't hit the wearer blown_kiss.preparePixelProjectile(target, user) blown_kiss.fire() qdel(src) @@ -531,7 +531,7 @@ blown_kiss.original = taker blown_kiss.fired_from = offerer blown_kiss.firer = offerer // don't hit ourself that would be really annoying - blown_kiss.impacted = list(offerer = TRUE) // just to make sure we don't hit the wearer + blown_kiss.impacted = list(WEAKREF(offerer) = TRUE) // just to make sure we don't hit the wearer blown_kiss.preparePixelProjectile(taker, offerer) blown_kiss.suppressed = SUPPRESSED_VERY // this also means it's a direct offer blown_kiss.fire() diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index 8db6b3556a0..259d38119ac 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -46,11 +46,13 @@ throw_range = 5 custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 5) breakouttime = 1 MINUTES + armor_type = /datum/armor/restraints_handcuffs + custom_price = PAYCHECK_COMMAND * 0.35 + + ///How long it takes to handcuff someone var/handcuff_time = 4 SECONDS ///Multiplier for handcuff time var/handcuff_time_mod = 1 - armor_type = /datum/armor/restraints_handcuffs - custom_price = PAYCHECK_COMMAND * 0.35 ///Sound that plays when starting to put handcuffs on someone var/cuffsound = 'sound/weapons/handcuffs.ogg' ///If set, handcuffs will be destroyed on application and leave behind whatever this is set to. @@ -70,51 +72,68 @@ fire = 50 acid = 50 -/obj/item/restraints/handcuffs/attack(mob/living/carbon/C, mob/living/user) - if(!istype(C)) +/obj/item/restraints/handcuffs/attack(mob/living/target_mob, mob/living/user) + if(!iscarbon(target_mob)) return - if(SEND_SIGNAL(C, COMSIG_CARBON_CUFF_ATTEMPTED, user) & COMSIG_CARBON_CUFF_PREVENT) + attempt_to_cuff(target_mob, user) // avoid locking up the attack chain with sleeps + +/// Handles all of the checks and application in a typical situation where someone attacks a carbon victim with the handcuff item. +/obj/item/restraints/handcuffs/proc/attempt_to_cuff(mob/living/carbon/victim, mob/living/user) + if(SEND_SIGNAL(victim, COMSIG_CARBON_CUFF_ATTEMPTED, user) & COMSIG_CARBON_CUFF_PREVENT) + victim.balloon_alert(user, "can't be handcuffed!") return if(iscarbon(user) && (HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))) //Clumsy people have a 50% chance to handcuff themselves instead of their target. to_chat(user, span_warning("Uh... how do those things work?!")) - apply_cuffs(user,user) + apply_cuffs(user, user) return + if(!isnull(victim.handcuffed)) + victim.balloon_alert(user, "already handcuffed!") + return + + if(victim.canBeHandcuffed()) + victim.balloon_alert(user, "can't be handcuffed!") + to_chat(user, span_warning("[victim] doesn't have two hands...")) + return + + victim.visible_message( + span_danger("[user] is trying to put [src] on [victim]!"), + span_userdanger("[user] is trying to put [src] on you!"), + ) + + if(victim.is_blind()) + to_chat(victim, span_userdanger("As you feel someone grab your wrists, [src] start digging into your skin!")) + + playsound(loc, cuffsound, 30, TRUE, -2) + log_combat(user, victim, "attempted to handcuff") + if(HAS_TRAIT(user, TRAIT_FAST_CUFFING)) handcuff_time_mod = 0.75 else handcuff_time_mod = 1 - if(!C.handcuffed) - if(C.canBeHandcuffed()) - C.visible_message(span_danger("[user] is trying to put [src] on [C]!"), \ - span_userdanger("[user] is trying to put [src] on you!")) - if(C.is_blind()) - to_chat(C, span_userdanger("As you feel someone grab your wrists, [src] start digging into your skin!")) - playsound(loc, cuffsound, 30, TRUE, -2) - log_combat(user, C, "attempted to handcuff") - if(do_after(user, handcuff_time * handcuff_time_mod, C, timed_action_flags = IGNORE_SLOWDOWNS) && C.canBeHandcuffed()) - if(iscyborg(user)) - apply_cuffs(C, user, TRUE) - else - apply_cuffs(C, user) - C.visible_message(span_notice("[user] handcuffs [C]."), \ - span_userdanger("[user] handcuffs you.")) - SSblackbox.record_feedback("tally", "handcuffs", 1, type) + if(!do_after(user, handcuff_time * handcuff_time_mod, victim, timed_action_flags = IGNORE_SLOWDOWNS) || !victim.canBeHandcuffed()) + victim.balloon_alert(user, "failed to handcuff!") + to_chat(user, span_warning("You fail to handcuff [victim]!")) + log_combat(user, victim, "failed to handcuff") + return + + apply_cuffs(victim, user, dispense = iscyborg(user)) + + victim.visible_message( + span_notice("[user] handcuffs [victim]."), + span_userdanger("[user] handcuffs you."), + ) + + log_combat(user, victim, "successfully handcuffed") + SSblackbox.record_feedback("tally", "handcuffs", 1, type) - log_combat(user, C, "handcuffed") - else - to_chat(user, span_warning("You fail to handcuff [C]!")) - log_combat(user, C, "failed to handcuff") - else - to_chat(user, span_warning("[C] doesn't have two hands...")) /** - * This handles handcuffing people + * When called, this instantly puts handcuffs on someone (if actually possible) * - * When called, this instantly puts handcuffs on someone (if possible) * Arguments: * * mob/living/carbon/target - Who is being handcuffed * * mob/user - Who or what is doing the handcuffing @@ -137,7 +156,6 @@ if(trashtype && !dispense) qdel(src) - return /** * # Alien handcuffs diff --git a/code/game/objects/items/implants/implantpad.dm b/code/game/objects/items/implants/implantpad.dm index 706fb29733d..0d0391126c9 100644 --- a/code/game/objects/items/implants/implantpad.dm +++ b/code/game/objects/items/implants/implantpad.dm @@ -10,6 +10,7 @@ throw_speed = 3 throw_range = 5 w_class = WEIGHT_CLASS_SMALL + interaction_flags_click = FORBID_TELEKINESIS_REACH ///The implant case currently inserted into the pad. var/obj/item/implantcase/inserted_case @@ -46,11 +47,9 @@ update_static_data_for_all_viewers() update_appearance(UPDATE_ICON) -/obj/item/implantpad/AltClick(mob/user) - . = ..() - if(!user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) - return +/obj/item/implantpad/click_alt(mob/user) remove_implant(user) + return CLICK_ACTION_SUCCESS /obj/item/implantpad/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) diff --git a/code/game/objects/items/inspector.dm b/code/game/objects/items/inspector.dm index 2f25e53c1fb..f96c1beb573 100644 --- a/code/game/objects/items/inspector.dm +++ b/code/game/objects/items/inspector.dm @@ -372,15 +372,16 @@ */ /obj/item/paper/fake_report/water grind_results = list(/datum/reagent/water = 5) + interaction_flags_click = NEED_DEXTERITY|NEED_HANDS -/obj/item/paper/fake_report/water/AltClick(mob/living/user, obj/item/I) - if(!user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS)) - return +/obj/item/paper/fake_report/water/click_alt(mob/living/user) var/datum/action/innate/origami/origami_action = locate() in user.actions if(origami_action?.active) //Origami masters can fold water - make_plane(user, I, /obj/item/paperplane/syndicate) + make_plane(user, /obj/item/paperplane/syndicate) else if(do_after(user, 1 SECONDS, target = src, progress=TRUE)) var/turf/open/target = get_turf(src) target.MakeSlippery(TURF_WET_WATER, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS) to_chat(user, span_notice("As you try to fold [src] into the shape of a plane, it disintegrates into water!")) qdel(src) + + return CLICK_ACTION_SUCCESS diff --git a/code/game/objects/items/machine_wand.dm b/code/game/objects/items/machine_wand.dm index 71ea2fae1b6..c1dd0bf382d 100644 --- a/code/game/objects/items/machine_wand.dm +++ b/code/game/objects/items/machine_wand.dm @@ -63,14 +63,15 @@ if(controlling_machine_or_bot) return controlling_machine_or_bot.ui_act(action, params, ui, state) -/obj/item/machine_remote/AltClick(mob/user) - . = ..() +/obj/item/machine_remote/click_alt(mob/user) if(moving_bug) //we have a bug in transit, so let's kill it. QDEL_NULL(moving_bug) + return CLICK_ACTION_BLOCKING if(!controlling_machine_or_bot) - return + return CLICK_ACTION_BLOCKING say("Remote control over [controlling_machine_or_bot] stopped.") remove_old_machine() + return CLICK_ACTION_SUCCESS /obj/item/machine_remote/afterattack(atom/target, mob/user, proximity_flag, click_parameters) . = ..() diff --git a/code/game/objects/items/mail.dm b/code/game/objects/items/mail.dm index 3a86d267af2..71968171d3a 100644 --- a/code/game/objects/items/mail.dm +++ b/code/game/objects/items/mail.dm @@ -514,7 +514,7 @@ return FALSE if(loc != user) return FALSE - mail_type = lowertext(mail_type) + mail_type = LOWER_TEXT(mail_type) var/mail_armed = tgui_alert(user, "Arm it?", "Mail Counterfeiting", list("Yes", "No")) == "Yes" if(isnull(mail_armed)) diff --git a/code/game/objects/items/paiwire.dm b/code/game/objects/items/paiwire.dm index fa5724ebb53..d590d4e9603 100644 --- a/code/game/objects/items/paiwire.dm +++ b/code/game/objects/items/paiwire.dm @@ -4,15 +4,15 @@ icon = 'icons/obj/stack_objects.dmi' icon_state = "wire1" item_flags = NOBLUDGEON - var/obj/machinery/machine //what machine we're currently hacking. + ///The current machine being hacked by the pAI cable. + var/obj/machinery/hacking_machine /obj/item/pai_cable/Destroy() - machine = null + hacking_machine = null return ..() - /obj/item/pai_cable/proc/plugin(obj/machinery/M, mob/living/user) if(!user.transferItemToLoc(src, M)) return user.visible_message(span_notice("[user] inserts [src] into a data port on [M]."), span_notice("You insert [src] into a data port on [M]."), span_hear("You hear the satisfying click of a wire jack fastening into place.")) - machine = M + hacking_machine = M diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm index bbbeb86602c..0d9b0909db2 100644 --- a/code/game/objects/items/pet_carrier.dm +++ b/code/game/objects/items/pet_carrier.dm @@ -66,9 +66,9 @@ open = TRUE update_appearance() -/obj/item/pet_carrier/AltClick(mob/living/user) - if(open || !user.can_perform_action(src)) - return +/obj/item/pet_carrier/click_alt(mob/living/user) + if(open) + return CLICK_ACTION_BLOCKING locked = !locked to_chat(user, span_notice("You flip the lock switch [locked ? "down" : "up"].")) if(locked) @@ -76,6 +76,7 @@ else playsound(user, 'sound/machines/boltsup.ogg', 30, TRUE) update_appearance() + return CLICK_ACTION_SUCCESS /obj/item/pet_carrier/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(user.combat_mode || !isliving(interacting_with)) diff --git a/code/game/objects/items/pillow.dm b/code/game/objects/items/pillow.dm index 1dad0a7fba5..659cc38f58b 100644 --- a/code/game/objects/items/pillow.dm +++ b/code/game/objects/items/pillow.dm @@ -102,16 +102,15 @@ if(pillow_trophy) . += span_notice("Alt-click to remove the tag!") -/obj/item/pillow/AltClick(mob/user) - . = ..() - if(!can_interact(user) || !user.can_hold_items(src)) - return +/obj/item/pillow/click_alt(mob/user) + if(!user.can_hold_items(src)) + return CLICK_ACTION_BLOCKING if(!pillow_trophy) balloon_alert(user, "no tag!") - return + return CLICK_ACTION_BLOCKING balloon_alert(user, "removing tag...") if(!do_after(user, 2 SECONDS, src)) - return + return CLICK_ACTION_BLOCKING if(last_fighter) pillow_trophy.desc = "A pillow tag taken from [last_fighter] after a gruesome pillow fight." user.put_in_hands(pillow_trophy) @@ -119,6 +118,7 @@ balloon_alert(user, "tag removed") playsound(user,'sound/items/poster_ripped.ogg', 50) update_appearance() + return CLICK_ACTION_SUCCESS /obj/item/pillow/update_appearance(updates) . = ..() diff --git a/code/game/objects/items/puzzle_pieces.dm b/code/game/objects/items/puzzle_pieces.dm index 77b07488d6c..1fabf13d31a 100644 --- a/code/game/objects/items/puzzle_pieces.dm +++ b/code/game/objects/items/puzzle_pieces.dm @@ -323,7 +323,7 @@ SSqueuelinks.add_to_queue(src, id, late_initialize_pop ? 0 : queue_size) return late_initialize_pop ? INITIALIZE_HINT_LATELOAD : . -/obj/machinery/puzzle/LateInitialize() +/obj/machinery/puzzle/post_machine_initialize() . = ..() if(late_initialize_pop && id && SSqueuelinks.queues[id]) SSqueuelinks.pop_link(id) diff --git a/code/game/objects/items/rcd/RPLD.dm b/code/game/objects/items/rcd/RPLD.dm index e5100d11c04..f8e38c5aadb 100644 --- a/code/game/objects/items/rcd/RPLD.dm +++ b/code/game/objects/items/rcd/RPLD.dm @@ -282,8 +282,9 @@ create_machine(target, user) -/obj/item/construction/plumbing/AltClick(mob/user) +/obj/item/construction/plumbing/click_alt(mob/user) ui_interact(user) + return CLICK_ACTION_SUCCESS /obj/item/construction/plumbing/proc/mouse_wheeled(mob/source, atom/A, delta_x, delta_y, params) SIGNAL_HANDLER diff --git a/code/game/objects/items/rcd/RWD.dm b/code/game/objects/items/rcd/RWD.dm index a20946e322f..0ee29e87a35 100644 --- a/code/game/objects/items/rcd/RWD.dm +++ b/code/game/objects/items/rcd/RWD.dm @@ -125,8 +125,7 @@ add_cable(user, cable) return TRUE -/obj/item/rwd/AltClick(mob/user) - . = ..() +/obj/item/rwd/click_alt(mob/user) if(!radial_menu) radial_menu = list( "Layer 1" = image(icon = 'icons/hud/radial.dmi', icon_state = "coil-red"), @@ -136,7 +135,7 @@ var/layer_result = show_radial_menu(user, src, radial_menu, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE, tooltips = TRUE) if(!check_menu(user)) - return + return CLICK_ACTION_BLOCKING switch(layer_result) if("Layer 1") cable_layer = CABLE_LAYER_1 @@ -145,6 +144,7 @@ if("Layer 3") cable_layer = CABLE_LAYER_3 update_appearance(UPDATE_ICON_STATE) + return CLICK_ACTION_SUCCESS /obj/item/rwd/proc/check_menu(mob/living/user) if(!istype(user)) diff --git a/code/game/objects/items/robot/items/hypo.dm b/code/game/objects/items/robot/items/hypo.dm index 8ab81a46234..bdb8387d95f 100644 --- a/code/game/objects/items/robot/items/hypo.dm +++ b/code/game/objects/items/robot/items/hypo.dm @@ -244,13 +244,12 @@ . += "Currently loaded: [selected_reagent ? "[selected_reagent]. [selected_reagent.description]" : "nothing."]" . += span_notice("Alt+Click to change transfer amount. Currently set to [amount_per_transfer_from_this]u.") -/obj/item/reagent_containers/borghypo/AltClick(mob/living/user) - . = ..() -/* SKYRAT REMOVAL START - Changing transfer amounts is now handled by the parent proc in modular files. - if(user.stat == DEAD || user != loc) - return //IF YOU CAN HEAR ME SET MY TRANSFER AMOUNT TO 1 - change_transfer_amount(user) -*/ // SKYRAT REMOVAL END +/* SKYRAT EDIT REMOVAL START - SEE master_files/code/modules/reagents/reagent_containers.dm +/obj/item/reagent_containers/borghypo/click_alt(mob/living/user) + + change_transfer_amount(user) + return CLICK_ACTION_SUCCESS +SKYRAT EDIT REMOVAL END */ /// Default Medborg Hypospray /obj/item/reagent_containers/borghypo/medical diff --git a/code/game/objects/items/robot/items/storage.dm b/code/game/objects/items/robot/items/storage.dm index 01541df5a9c..2d91128adb6 100644 --- a/code/game/objects/items/robot/items/storage.dm +++ b/code/game/objects/items/robot/items/storage.dm @@ -50,10 +50,11 @@ stored.attack_self(user) //Alt click drops the stored item. -/obj/item/borg/apparatus/AltClick(mob/living/silicon/robot/user) +/obj/item/borg/apparatus/click_alt(mob/living/silicon/robot/user) if(!stored || !issilicon(user)) - return ..() + return CLICK_ACTION_BLOCKING stored.forceMove(user.drop_location()) + return CLICK_ACTION_SUCCESS /obj/item/borg/apparatus/pre_attack(atom/atom, mob/living/user, params) if(stored) @@ -244,16 +245,16 @@ bag = mutable_appearance(icon, icon_state = "evidenceobj") // empty bag . += bag -/obj/item/borg/apparatus/organ_storage/AltClick(mob/living/silicon/robot/user) - . = ..() - if(stored) - var/obj/item/organ = stored - user.visible_message(span_notice("[user] dumps [organ] from [src]."), span_notice("You dump [organ] from [src].")) - cut_overlays() - organ.forceMove(get_turf(src)) - else +/obj/item/borg/apparatus/organ_storage/click_alt(mob/living/silicon/robot/user) + if(!stored) to_chat(user, span_notice("[src] is empty.")) - return + return CLICK_ACTION_BLOCKING + + var/obj/item/organ = stored + user.visible_message(span_notice("[user] dumps [organ] from [src]."), span_notice("You dump [organ] from [src].")) + cut_overlays() + organ.forceMove(get_turf(src)) + return CLICK_ACTION_SUCCESS ///Apparatus to allow Engineering/Sabo borgs to manipulate any material sheets. /obj/item/borg/apparatus/sheet_manipulator diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index efc541aee34..d0fd45064d2 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -40,7 +40,10 @@ one_use = TRUE /obj/item/borg/upgrade/rename/attack_self(mob/user) - heldname = sanitize_name(tgui_input_text(user, "Enter new robot name", "Cyborg Reclassification", heldname, MAX_NAME_LEN), allow_numbers = TRUE) + var/new_heldname = sanitize_name(tgui_input_text(user, "Enter new robot name", "Cyborg Reclassification", heldname, MAX_NAME_LEN), allow_numbers = TRUE) + if(!new_heldname || !user.is_holding(src)) + return + heldname = new_heldname user.log_message("set \"[heldname]\" as a name in a cyborg reclassification board at [loc_name(user)]", LOG_GAME) /obj/item/borg/upgrade/rename/action(mob/living/silicon/robot/R, user = usr) @@ -398,6 +401,10 @@ /obj/item/borg/upgrade/hypospray/action(mob/living/silicon/robot/R, user = usr) . = ..() + var/obj/item/borg/upgrade/hypospray/U = locate() in R + if(U) + to_chat(user, span_warning("This unit is already equipped with an expanded hypospray synthesiser!")) //check to see if we already have this module + return FALSE if(.) for(var/obj/item/reagent_containers/borghypo/medical/H in R.model.modules) H.upgrade_hypo() @@ -428,6 +435,7 @@ found_hypo = TRUE if(!found_hypo) + to_chat(user, span_warning("This unit is already equipped with a piercing hypospray upgrade!")) //check to see if we already have this module return FALSE /obj/item/borg/upgrade/piercing_hypospray/deactivate(mob/living/silicon/robot/R, user = usr) @@ -448,6 +456,10 @@ /obj/item/borg/upgrade/defib/action(mob/living/silicon/robot/R, user = usr) . = ..() if(.) + var/obj/item/borg/upgrade/defib/U = locate() in R + if(U) + to_chat(user, span_warning("This unit is already equipped with a defibrillator module!")) //check to see if we already have this module + return FALSE var/obj/item/borg/upgrade/defib/backpack/BP = locate() in R //If a full defib unit was used to upgrade prior, we can just pop it out now and replace if(BP) BP.deactivate(R, user) @@ -504,12 +516,11 @@ /obj/item/borg/upgrade/processor/action(mob/living/silicon/robot/R, user = usr) . = ..() if(.) - var/obj/item/surgical_processor/SP = locate() in R.model.modules // BUBBER EDIT added duiplication prevention - if(SP) - to_chat(user, span_warning("This unit is already equipped with A Surgical Processor!!")) + var/obj/item/borg/upgrade/processor/U = locate() in R + if(U) + to_chat(user, span_warning("This unit is already equipped with a surgical processor module!")) //check to see if we already have this module return FALSE - - SP = new(R.model) + var/obj/item/surgical_processor/SP = new(R.model) R.model.basic_modules += SP R.model.add_module(SP, FALSE, TRUE) diff --git a/code/game/objects/items/spear.dm b/code/game/objects/items/spear.dm index 1237c3587c9..02cbd3f7239 100644 --- a/code/game/objects/items/spear.dm +++ b/code/game/objects/items/spear.dm @@ -157,13 +157,12 @@ . = ..() . += span_notice("Alt-click to set your war cry.") -/obj/item/spear/explosive/AltClick(mob/user) - if(user.can_perform_action(src)) - ..() - if(istype(user) && loc == user) - var/input = tgui_input_text(user, "What do you want your war cry to be? You will shout it when you hit someone in melee.", "War Cry", max_length = 50) - if(input) - src.war_cry = input +/obj/item/spear/explosive/click_alt(mob/user) + var/input = tgui_input_text(user, "What do you want your war cry to be? You will shout it when you hit someone in melee.", "War Cry", max_length = 50) + if(input) + war_cry = input + return CLICK_ACTION_SUCCESS + /obj/item/spear/explosive/afterattack(atom/movable/AM, mob/user, proximity) . = ..() diff --git a/code/game/objects/items/stacks/bscrystal.dm b/code/game/objects/items/stacks/bscrystal.dm index 5c87ac46842..5e0d5254408 100644 --- a/code/game/objects/items/stacks/bscrystal.dm +++ b/code/game/objects/items/stacks/bscrystal.dm @@ -70,6 +70,7 @@ icon = 'icons/obj/stack_objects.dmi' icon_state = "polycrystal" inhand_icon_state = null + gulag_valid = TRUE singular_name = "bluespace polycrystal" desc = "A stable polycrystal, made of fused-together bluespace crystals. You could probably break one off." mats_per_unit = list(/datum/material/bluespace=SHEET_MATERIAL_AMOUNT) @@ -77,7 +78,6 @@ 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 = 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/medical.dm b/code/game/objects/items/stacks/medical.dm index 1f33384b393..59c65411805 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -35,7 +35,7 @@ /// Time it takes to assess injuries when looping healing var/assessing_injury_delay = 1 SECONDS -/obj/item/stack/medical/interact_with_atom(atom/interacting_with, mob/living/user) +/obj/item/stack/medical/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!isliving(interacting_with)) return NONE if(!begin_heal_loop(interacting_with, user)) @@ -419,11 +419,11 @@ return return ..() -/obj/item/stack/medical/mesh/AltClick(mob/living/user) +/obj/item/stack/medical/mesh/click_alt(mob/living/user) if(!is_open) balloon_alert(user, "open it first!") - return - return ..() + return CLICK_ACTION_BLOCKING + return CLICK_ACTION_SUCCESS /obj/item/stack/medical/mesh/attack_hand(mob/user, list/modifiers) if(!is_open && user.get_inactive_held_item() == src) diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index d6bd65afe31..1f66b80cf55 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -27,7 +27,6 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \ merge_type = /obj/item/stack/sheet/glass grind_results = list(/datum/reagent/silicon = 20) material_type = /datum/material/glass - point_value = 1 tableVariant = /obj/structure/table/glass matter_amount = 4 cost = SHEET_MATERIAL_AMOUNT @@ -159,7 +158,6 @@ 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 = 12 matter_amount = 6 tableVariant = /obj/structure/table/reinforced/rglass @@ -197,7 +195,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 = 69 + gulag_valid = TRUE 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 0620d82cd9b..1b3d66a7dae 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 = 75 + gulag_valid = TRUE 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 = 60 + gulag_valid = TRUE 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 = 60 + gulag_valid = TRUE 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 = 60 + gulag_valid = TRUE 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 = 60 + gulag_valid = TRUE 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 = 150 + gulag_valid = TRUE 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 = 60 + gulag_valid = TRUE 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 = 135 + gulag_valid = TRUE 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 = 300 + gulag_valid = TRUE 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 = 360 + gulag_valid = TRUE 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 e5ba265e98e..4591edfb2a6 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -157,7 +157,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 = 6 + gulag_valid = TRUE tableVariant = /obj/structure/table material_type = /datum/material/iron matter_amount = 4 @@ -284,7 +284,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 = 69 + gulag_valid = TRUE tableVariant = /obj/structure/table/reinforced material_flags = NONE matter_amount = 12 diff --git a/code/game/objects/items/stacks/sheets/sheets.dm b/code/game/objects/items/stacks/sheets/sheets.dm index 530a3573f7c..8b81953528e 100644 --- a/code/game/objects/items/stacks/sheets/sheets.dm +++ b/code/game/objects/items/stacks/sheets/sheets.dm @@ -14,7 +14,10 @@ novariants = FALSE material_flags = MATERIAL_EFFECTS var/sheettype = null //this is used for girders in the creation of walls/false walls - var/point_value = 0 //turn-in value for the gulag stacker - loosely relative to its rarity. + ///If true, this is worth points in the gulag labour stacker + var/gulag_valid = FALSE + ///Set to true if this is vended from a material storage + var/manufactured = FALSE ///What type of wall does this sheet spawn var/walltype /// whether this sheet can be sniffed by the material sniffer @@ -32,11 +35,24 @@ GLOB.sniffable_sheets -= src return ..() +/obj/item/stack/sheet/examine(mob/user) + . = ..() + if (manufactured && gulag_valid) + . += "It has been embossed with a manufacturer's mark of guaranteed quality." + /obj/item/stack/sheet/add(_amount) . = ..() if(sniffable && amount >= 10 && is_station_level(z)) GLOB.sniffable_sheets |= src +/obj/item/stack/sheet/merge(obj/item/stack/sheet/target_stack, limit) + . = ..() + manufactured = manufactured && target_stack.manufactured + +/obj/item/stack/sheet/copy_evidences(obj/item/stack/sheet/from) + . = ..() + manufactured = from.manufactured + /// removing from sniffable handled by the sniffer itself when it checks for targets /** diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 7a025bc6bcc..18a95cd77d3 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -196,11 +196,11 @@ /obj/item/stack/proc/update_weight() if(amount <= (max_amount * (1/3))) - w_class = clamp(full_w_class-2, WEIGHT_CLASS_TINY, full_w_class) + update_weight_class(clamp(full_w_class-2, WEIGHT_CLASS_TINY, full_w_class)) else if (amount <= (max_amount * (2/3))) - w_class = clamp(full_w_class-1, WEIGHT_CLASS_TINY, full_w_class) + update_weight_class(clamp(full_w_class-1, WEIGHT_CLASS_TINY, full_w_class)) else - w_class = full_w_class + update_weight_class(full_w_class) /obj/item/stack/update_icon_state() if(novariants) diff --git a/code/game/objects/items/stacks/telecrystal.dm b/code/game/objects/items/stacks/telecrystal.dm index a6bbe3bfe19..dd1b74eb106 100644 --- a/code/game/objects/items/stacks/telecrystal.dm +++ b/code/game/objects/items/stacks/telecrystal.dm @@ -11,7 +11,7 @@ merge_type = /obj/item/stack/telecrystal novariants = FALSE -/obj/item/stack/telecrystal/interact_with_atom(atom/interacting_with, mob/living/user) +/obj/item/stack/telecrystal/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(interacting_with != user) //You can't go around smacking people with crystals to find out if they have an uplink or not. return NONE diff --git a/code/game/objects/items/stacks/wrap.dm b/code/game/objects/items/stacks/wrap.dm index 4a8a1c1871f..49bac7d2d6d 100644 --- a/code/game/objects/items/stacks/wrap.dm +++ b/code/game/objects/items/stacks/wrap.dm @@ -36,13 +36,14 @@ //Set layers to these colors, base then ribbon set_greyscale(colors = list(generated_base_color, generated_ribbon_color)) -/obj/item/stack/wrapping_paper/AltClick(mob/user, modifiers) +/obj/item/stack/wrapping_paper/click_alt(mob/user) var/new_base = input(user, "", "Select a base color", color) as color var/new_ribbon = input(user, "", "Select a ribbon color", color) as color - if(!user.can_perform_action(src)) - return + if(!new_base || !new_ribbon) + return CLICK_ACTION_BLOCKING + set_greyscale(colors = list(new_base, new_ribbon)) - return TRUE + return CLICK_ACTION_SUCCESS //preset wrapping paper meant to fill the original color configuration /obj/item/stack/wrapping_paper/xmas @@ -135,7 +136,7 @@ item.forceMove(parcel) var/size = round(item.w_class) parcel.name = "[weight_class_to_text(size)] parcel" - parcel.w_class = size + parcel.update_weight_class(size) size = min(size, 5) parcel.base_icon_state = "deliverypackage[size]" parcel.update_icon() diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm index d72a57f07f1..cc548be16d2 100644 --- a/code/game/objects/items/storage/bags.dm +++ b/code/game/objects/items/storage/bags.dm @@ -360,23 +360,30 @@ /obj/item/storage/bag/tray/Initialize(mapload) . = ..() atom_storage.max_specific_storage = WEIGHT_CLASS_BULKY //Plates are required bulky to keep them out of backpacks - atom_storage.set_holdable(list( - /obj/item/clothing/mask/cigarette, - /obj/item/food, - /obj/item/kitchen, - /obj/item/lighter, - /obj/item/organ, - /obj/item/plate, - /obj/item/reagent_containers/condiment, - /obj/item/reagent_containers/cup, - /obj/item/rollingpaper, - /obj/item/storage/box/gum, - /obj/item/storage/box/matches, - /obj/item/storage/fancy, - /obj/item/trash, - )) //Should cover: Bottles, Beakers, Bowls, Booze, Glasses, Food, Food Containers, Food Trash, Organs, Tobacco Products, Lighters, and Kitchen Tools. + atom_storage.set_holdable( + can_hold_list = list( + /obj/item/clothing/mask/cigarette, + /obj/item/food, + /obj/item/kitchen, + /obj/item/lighter, + /obj/item/organ, + /obj/item/plate, + /obj/item/reagent_containers/condiment, + /obj/item/reagent_containers/cup, + /obj/item/rollingpaper, + /obj/item/storage/box/gum, + /obj/item/storage/box/matches, + /obj/item/storage/fancy, + /obj/item/trash, + ), + cant_hold_list = list( + /obj/item/plate/oven_tray, + /obj/item/reagent_containers/cup/soup_pot, + ), + ) //Should cover: Bottles, Beakers, Bowls, Booze, Glasses, Food, Food Containers, Food Trash, Organs, Tobacco Products, Lighters, and Kitchen Tools. atom_storage.insert_preposition = "on" - atom_storage.max_slots = 7 + atom_storage.max_slots = 8 + atom_storage.max_total_storage = 16 /obj/item/storage/bag/tray/attack(mob/living/M, mob/living/user) . = ..() diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index 451dc82c89c..ebfa73aa2f9 100644 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -839,6 +839,7 @@ inhand_icon_state = "sheath" worn_icon_state = "sheath" w_class = WEIGHT_CLASS_BULKY + interaction_flags_click = NEED_DEXTERITY|NEED_HANDS /obj/item/storage/belt/sabre/Initialize(mapload) . = ..() @@ -854,9 +855,7 @@ if(length(contents)) . += span_notice("Alt-click it to quickly draw the blade.") -/obj/item/storage/belt/sabre/AltClick(mob/user) - if(!user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS)) - return +/obj/item/storage/belt/sabre/click_alt(mob/user) if(length(contents)) var/obj/item/I = contents[1] user.visible_message(span_notice("[user] takes [I] out of [src]."), span_notice("You take [I] out of [src].")) @@ -864,6 +863,7 @@ update_appearance() else balloon_alert(user, "it's empty!") + return CLICK_ACTION_SUCCESS /obj/item/storage/belt/sabre/update_icon_state() icon_state = initial(inhand_icon_state) diff --git a/code/game/objects/items/storage/boxes/engineering_boxes.dm b/code/game/objects/items/storage/boxes/engineering_boxes.dm index de975d9dbfe..a46703ec8bf 100644 --- a/code/game/objects/items/storage/boxes/engineering_boxes.dm +++ b/code/game/objects/items/storage/boxes/engineering_boxes.dm @@ -24,10 +24,7 @@ /obj/item/storage/box/material/Initialize(mapload) . = ..() - atom_storage.allow_big_nesting = TRUE - atom_storage.max_slots = 99 - atom_storage.max_specific_storage = WEIGHT_CLASS_GIGANTIC - atom_storage.max_total_storage = 99 + atom_storage.max_specific_storage = WEIGHT_CLASS_GIGANTIC //This needs to be set here too because the parent type overrides it again /obj/item/storage/box/material/PopulateContents() //less uranium because radioactive var/static/items_inside = list( @@ -51,6 +48,11 @@ /obj/item/stack/sheet/plastic/fifty=1, /obj/item/stack/sheet/runed_metal/fifty=1, ) + //This needs to be done here and not in Initialize() because the stacks get merged and fall out when their weight updates if this is set after PopulateContents() + atom_storage.allow_big_nesting = TRUE + atom_storage.max_slots = 99 + atom_storage.max_specific_storage = WEIGHT_CLASS_GIGANTIC + atom_storage.max_total_storage = 99 generate_items_inside(items_inside,src) /obj/item/storage/box/debugtools diff --git a/code/game/objects/items/storage/boxes/service_boxes.dm b/code/game/objects/items/storage/boxes/service_boxes.dm index 8dcc1f4f6b6..6dc790cc495 100644 --- a/code/game/objects/items/storage/boxes/service_boxes.dm +++ b/code/game/objects/items/storage/boxes/service_boxes.dm @@ -204,6 +204,22 @@ for(var/i in 1 to 5) new /obj/item/reagent_containers/spray/chemsprayer/party(src) +/obj/item/storage/box/balloons + name = "box of long balloons" + desc = "A completely randomized and wacky box of long balloons, harvested straight from balloon farms on the clown planet." + illustration = "balloon" + +/obj/item/storage/box/balloons/Initialize(mapload) + . = ..() + atom_storage.max_slots = 24 + atom_storage.set_holdable(list(/obj/item/toy/balloon/long)) + atom_storage.max_total_storage = 24 + atom_storage.allow_quick_gather = FALSE + +/obj/item/storage/box/balloons/PopulateContents() + for(var/i in 1 to 24) + new /obj/item/toy/balloon/long(src) + /obj/item/storage/box/stickers name = "box of stickers" desc = "A box full of random stickers. Do give to the clown." diff --git a/code/game/objects/items/storage/fancy.dm b/code/game/objects/items/storage/fancy.dm index 95eb304509f..1e6cd6432ca 100644 --- a/code/game/objects/items/storage/fancy.dm +++ b/code/game/objects/items/storage/fancy.dm @@ -240,13 +240,13 @@ . = ..() quick_remove_item(/obj/item/clothing/mask/cigarette, user) -/obj/item/storage/fancy/cigarettes/AltClick(mob/user) - . = ..() +/obj/item/storage/fancy/cigarettes/click_alt(mob/user) var/obj/item/lighter = locate(/obj/item/lighter) in contents if(lighter) quick_remove_item(lighter, user) else quick_remove_item(/obj/item/clothing/mask/cigarette, user) + return CLICK_ACTION_SUCCESS /// Removes an item from the packet if there is one /obj/item/storage/fancy/cigarettes/proc/quick_remove_item(obj/item/grabbies, mob/user) diff --git a/code/game/objects/items/storage/lockbox.dm b/code/game/objects/items/storage/lockbox.dm index 8e542ebcc44..3a0b15b7d28 100644 --- a/code/game/objects/items/storage/lockbox.dm +++ b/code/game/objects/items/storage/lockbox.dm @@ -121,13 +121,11 @@ if(!atom_storage.locked) . += span_notice("Alt-click to [open ? "close":"open"] it.") -/obj/item/storage/lockbox/medal/AltClick(mob/user) - if(!user.can_perform_action(src)) - return +/obj/item/storage/lockbox/medal/click_alt(mob/user) if(!atom_storage.locked) open = (open ? FALSE : TRUE) update_appearance() - ..() + return CLICK_ACTION_SUCCESS /obj/item/storage/lockbox/medal/PopulateContents() new /obj/item/clothing/accessory/medal/gold/captain(src) diff --git a/code/game/objects/items/tanks/tank_types.dm b/code/game/objects/items/tanks/tank_types.dm index 064a749521e..b21deb35581 100644 --- a/code/game/objects/items/tanks/tank_types.dm +++ b/code/game/objects/items/tanks/tank_types.dm @@ -7,12 +7,14 @@ * Emergency Oxygen * Generic */ +/obj/item/tank/internals + interaction_flags_click = FORBID_TELEKINESIS_REACH|NEED_HANDS + /// Allows carbon to toggle internals via AltClick of the equipped tank. -/obj/item/tank/internals/AltClick(mob/user) - ..() - if((loc == user) && user.can_perform_action(src, FORBID_TELEKINESIS_REACH|NEED_HANDS)) - toggle_internals(user) +/obj/item/tank/internals/click_alt(mob/user) + toggle_internals(user) + return CLICK_ACTION_SUCCESS /obj/item/tank/internals/examine(mob/user) . = ..() diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index 8772e2f41c9..72c84c9ee99 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -460,7 +460,7 @@ tank_assembly = assembly //Tell the tank about its assembly part assembly.master = src //Tell the assembly about its new owner assembly.on_attach() - w_class = WEIGHT_CLASS_BULKY + update_weight_class(WEIGHT_CLASS_BULKY) balloon_alert(user, "bomb assembled") update_appearance(UPDATE_OVERLAYS) @@ -474,7 +474,7 @@ user.put_in_hands(tank_assembly) tank_assembly.master = null tank_assembly = null - w_class = initial(w_class) + update_weight_class(initial(w_class)) update_appearance(UPDATE_OVERLAYS) /// Ignites the contents of the tank. Called when receiving a signal if the tank is welded and has an igniter attached. diff --git a/code/game/objects/items/tcg/tcg_machines.dm b/code/game/objects/items/tcg/tcg_machines.dm index 767592535f7..78854afdd5b 100644 --- a/code/game/objects/items/tcg/tcg_machines.dm +++ b/code/game/objects/items/tcg/tcg_machines.dm @@ -91,7 +91,7 @@ GLOBAL_LIST_EMPTY(tcgcard_machine_radial_choices) /obj/machinery/trading_card_holder/attack_hand_secondary(mob/user) if(isnull(current_summon)) var/card_name = tgui_input_text(user, "Insert card name", "Blank Card Naming", "blank card", MAX_NAME_LEN) - if(isnull(card_name)) + if(isnull(card_name) || !user.can_perform_action(src)) return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN current_summon = new /obj/structure/trading_card_summon/blank(locate(x + summon_offset_x, y + summon_offset_y, z)) icon_state = "card_holder_active" diff --git a/code/game/objects/items/tools/spess_knife.dm b/code/game/objects/items/tools/spess_knife.dm index 0b0061de7a4..9fd5dbb0158 100644 --- a/code/game/objects/items/tools/spess_knife.dm +++ b/code/game/objects/items/tools/spess_knife.dm @@ -60,10 +60,10 @@ mistake_occured = TRUE if(isnull(tool_behaviour)) - w_class = WEIGHT_CLASS_TINY + update_weight_class(WEIGHT_CLASS_TINY) balloon_alert(user, "folded") else - w_class = WEIGHT_CLASS_SMALL + update_weight_class(WEIGHT_CLASS_SMALL) balloon_alert(user, mistake_occured ? "oops! [tool_behaviour] out" : "[tool_behaviour] out") update_tool_parameters() diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index 31efb0ef273..1bb2ac365df 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -134,7 +134,7 @@ LAZYREMOVE(update_overlays_on_z, sparks) target.cut_overlay(sparks) -/obj/item/weldingtool/interact_with_atom(atom/interacting_with, mob/living/user) +/obj/item/weldingtool/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!ishuman(interacting_with)) return NONE if(user.combat_mode) @@ -163,10 +163,12 @@ if(!proximity) return - if(isOn()) + if(isOn() && ismovable(attacked_atom)) + use(1) + var/turf/location = get_turf(user) + location.hotspot_expose(700, 50, 1) . |= AFTERATTACK_PROCESSED_ITEM if (!QDELETED(attacked_atom) && isliving(attacked_atom)) // can't ignite something that doesn't exist - handle_fuel_and_temps(1, user) var/mob/living/attacked_mob = attacked_atom if(attacked_mob.ignite_mob()) message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(attacked_mob)] on fire with [src] at [AREACOORD(user)]") @@ -180,21 +182,6 @@ return . -/obj/item/weldingtool/attack_qdeleted(atom/attacked_atom, mob/user, proximity) - . = ..() - if(!proximity) - return - - if(isOn()) - handle_fuel_and_temps(1, user) - - if(!QDELETED(attacked_atom) && isliving(attacked_atom)) // can't ignite something that doesn't exist - var/mob/living/attacked_mob = attacked_atom - if(attacked_mob.ignite_mob()) - message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(attacked_mob)] on fire with [src] at [AREACOORD(user)].") - user.log_message("set [key_name(attacked_mob)] on fire with [src]", LOG_ATTACK) - - /obj/item/weldingtool/attack_self(mob/user) if(src.reagents.has_reagent(/datum/reagent/toxin/plasma)) message_admins("[ADMIN_LOOKUPFLW(user)] activated a rigged welder at [AREACOORD(user)].") @@ -204,11 +191,6 @@ update_appearance() -/obj/item/weldingtool/proc/handle_fuel_and_temps(used = 0, mob/living/user) - use(used) - var/turf/location = get_turf(user) - location.hotspot_expose(700, 50, 1) - /// Returns the amount of fuel in the welder /obj/item/weldingtool/proc/get_fuel() return reagents.get_reagent_amount(/datum/reagent/fuel) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 67192b829a7..6a5b6357a8f 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -39,8 +39,8 @@ /obj/item/toy/waterballoon name = "water balloon" desc = "A translucent balloon. There's nothing in it." - icon = 'icons/obj/toys/toy.dmi' - icon_state = "waterballoon-e" + icon = 'icons/obj/toys/balloons.dmi' + icon_state = "balloon_red-e" inhand_icon_state = "balloon-empty" /obj/item/toy/waterballoon/Initialize(mapload) @@ -107,15 +107,15 @@ icon_state = "waterballoon" inhand_icon_state = "balloon" else - icon_state = "waterballoon-e" + icon_state = "balloon_red-e" inhand_icon_state = "balloon-empty" return ..() -#define BALLOON_COLORS list("red", "blue", "green", "yellow") +#define BALLOON_COLORS list("red", "blue", "green", "yellow", "orange", "purple") /obj/item/toy/balloon name = "balloon" - desc = "No birthday is complete without it." + desc = "No birthday is complete without it. Sealed with a mechanical bluespace wrap so it remains floating no matter what." icon = 'icons/obj/toys/balloons.dmi' icon_state = "balloon" inhand_icon_state = "balloon" @@ -127,6 +127,68 @@ throw_range = 7 force = 0 var/random_color = TRUE + /// the string of the dmi state the balloon has while on the floor. + var/world_state + /// the string of the dmi state the balloon has while in your inventory. + var/storage_state + /// the string describing the name of balloon's current colour. + var/current_color + +/obj/item/toy/balloon/long + name = "long balloon" + desc = "A perfect balloon to contort into goofy forms. Sealed with a mechanical bluespace wrap so it remains floating no matter what." + icon_state = "balloon_long" + inhand_icon_state = "balloon" + w_class = WEIGHT_CLASS_NORMAL + /// Combinations of balloon colours to make specific animals. + var/list/balloon_combos = list( + list("red", "blue") = /obj/item/toy/balloon_animal/guy, + list("red", "green") = /obj/item/toy/balloon_animal/nukie, + list("red", "yellow") = /obj/item/toy/balloon_animal/clown, + list("red", "orange") = /obj/item/toy/balloon_animal/cat, + list("red", "purple") = /obj/item/toy/balloon_animal/fly, + list("blue", "green") = /obj/item/toy/balloon_animal/podguy, + list("blue", "yellow") = /obj/item/toy/balloon_animal/ai, + list("blue", "orange") = /obj/item/toy/balloon_animal/dog, + list("blue", "purple") = /obj/item/toy/balloon_animal/xeno, + list("green", "yellow") = /obj/item/toy/balloon_animal/banana, + list("green", "orange") = /obj/item/toy/balloon_animal/lizard, + list("green", "purple") = /obj/item/toy/balloon_animal/slime, + list("yellow", "orange") = /obj/item/toy/balloon_animal/moth, + list("yellow", "purple") = /obj/item/toy/balloon_animal/ethereal, + list("orange", "purple") = /obj/item/toy/balloon_animal/plasmaman, + ) + +/obj/item/toy/balloon/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change) + . = ..() + if(isturf(loc)) + icon_state = "[world_state]" + else + icon_state = "[storage_state]" + update_appearance() + +/obj/item/toy/balloon/long/attackby(obj/item/attacking_item, mob/living/user, params) + if(!istype(attacking_item, /obj/item/toy/balloon/long) || !HAS_TRAIT(user, TRAIT_BALLOON_SUTRA)) + return ..() + + var/obj/item/toy/balloon/long/hit_by = attacking_item + if(hit_by.current_color == current_color) + to_chat(user, span_warning("You must use balloons of different colours to do that!")) + return ..() + visible_message( + span_notice("[user.name] starts contorting up a balloon animal!"), + blind_message = span_hear("You hear balloons being contorted."), + vision_distance = 3, + ignored_mobs = user, + ) + for(var/list/pair_of_colors in balloon_combos) + if((hit_by.current_color == pair_of_colors[1] && current_color == pair_of_colors[2]) || (current_color == pair_of_colors[1] && hit_by.current_color == pair_of_colors[2])) + var/path_to_spawn = balloon_combos[pair_of_colors] + user.put_in_hands(new path_to_spawn) + break + qdel(hit_by) + qdel(src) + return TRUE /obj/item/toy/balloon/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/ammo_casing/foam_dart) && ismonkey(user)) @@ -157,17 +219,27 @@ . = ..() if(random_color) var/chosen_balloon_color = pick(BALLOON_COLORS) + current_color = "[chosen_balloon_color]" name = "[chosen_balloon_color] [name]" icon_state = "[icon_state]_[chosen_balloon_color]" inhand_icon_state = icon_state + world_state = "[icon_state]" + storage_state = "[icon_state]_storage" /obj/item/toy/balloon/corgi name = "corgi balloon" - desc = "A balloon with a corgi face on it. For the all year good boys." + desc = "A balloon in the shape of a corgi's head. For the all year good boys." icon_state = "corgi" inhand_icon_state = "corgi" random_color = FALSE +/obj/item/toy/balloon/heart + name = "heart balloon" + desc = "A balloon in the shape of a heart. How lovely" + icon_state = "heart" + inhand_icon_state = "heart" + random_color = FALSE + /obj/item/toy/balloon/syndicate name = "syndicate balloon" desc = "There is a tag on the back that reads \"FUK NT!11!\"." @@ -200,6 +272,96 @@ #undef BALLOON_COLORS +/* +* Balloon animals +*/ + +/obj/item/toy/balloon_animal + name = "balloon animal" + desc = "You shouldn't have this." + icon = 'icons/obj/toys/balloons.dmi' + icon_state = "balloon_guy" + throwforce = 0 + throw_speed = 2 + throw_range = 5 + force = 0 + +/obj/item/toy/balloon_animal/guy + name = "balloon guy" + desc = "A balloon effigy of the everyday standard issue human guy. Wonder if he pays balloon taxes. He probably evades them." + icon_state = "balloon_guy" + +/obj/item/toy/balloon_animal/nukie + name = "balloon nukie" + desc = "A balloon effigy of syndicate's nuclear operative. Either made to appease them and pray for survival, or to poke fun at them." + icon_state = "balloon_nukie" + +/obj/item/toy/balloon_animal/clown + name = "balloon clown" + desc = "A balloon clown, smiling from ear to ear and beyond!" + icon_state = "balloon_clown" + +/obj/item/toy/balloon_animal/cat + name = "balloon cat" + desc = "Without the sharp claws, balloon cats are possibly cuter than their live counterparts, though not as relatable, warm and fuzzy." + icon_state = "balloon_cat" + +/obj/item/toy/balloon_animal/fly + name = "balloon fly" + desc = "A balloon effigy of a flyperson. Thankfully, it doesn't come with balloon vomit." + icon_state = "balloon_fly" + +/obj/item/toy/balloon_animal/podguy + name = "balloon podguy" + desc = "A balloon effigy of a podperson. Though, actual podpeople have heads and not stalks and leaves." + icon_state = "balloon_podguy" + +/obj/item/toy/balloon_animal/ai + name = "balloon ai core" + desc = "A somewhat unrealistic balloon effigy of the station's AI core. Actual AI propably wouldn't smile like this." + icon_state = "balloon_ai" + +/obj/item/toy/balloon_animal/dog + name = "balloon dog" + desc = "A balloon effigy of the best boy. It cannot truly compare, but it makes an effort." + icon_state = "balloon_dog" + +/obj/item/toy/balloon_animal/xeno + name = "balloon xeno" + desc = "A balloon effigy of a spooky xeno! Too squishy to scare anyone itself, though." + icon_state = "balloon_xeno" + +/obj/item/toy/balloon_animal/banana + name = "balloon banana" + desc = "A balloon banana. This one can't be slipped on. Good for psychological warfare, though." + icon_state = "balloon_banana" + +/obj/item/toy/balloon_animal/lizard + name = "balloon lizard" + desc = "A balloon effigy of a lizard. One of the first species to adapt to clown planet's culture. Perhaps because they are naturally laughable?" + icon_state = "balloon_lizard" + +/obj/item/toy/balloon_animal/slime + name = "balloon slime" + desc = "A balloon effigy of single specimen of the galaxy-wide slime scourge, of purple variety. Slimes tried to invade clown planet once. They got quickly washed out by water-spitting flowers, though." + icon_state = "balloon_slime" + +/obj/item/toy/balloon_animal/moth + name = "balloon moth" + desc = "A balloon effigy of a common member of moth flotillas. Very few of them ever decide to settle on the clown planet, but those who do have the best 'piece-of-cloth-dissapearing' acts." + icon_state = "balloon_moth" + +/obj/item/toy/balloon_animal/ethereal + name = "balloon ethereal" + desc = "A balloon effigy of an ethereal artisan. Clownery is one form of art, and as such, ethereals were both drawn to and readily accepted at clown planet. Don't mind the lighbulb head, it's art too." + icon_state = "balloon_ethereal" + +/obj/item/toy/balloon_animal/plasmaman + name = "balloon plasmaman" + desc = "A balloon effigy of a plasmaman. Among the rarest on the clown planet, only having appeared recently thanks to ready trade between clown planet and NT." + icon_state = "balloon_plasmaman" + + /* * Captain's Aid */ @@ -1240,7 +1402,7 @@ //Add changing looks when i feel suicidal about making 20 inhands for these. /obj/item/toy/dummy/attack_self(mob/user) var/new_name = tgui_input_text(usr, "What would you like to name the dummy?", "Doll Name", doll_name, MAX_NAME_LEN) - if(!new_name) + if(!new_name || !user.is_holding(src)) return doll_name = new_name to_chat(user, span_notice("You name the dummy as \"[doll_name]\".")) diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 1f2078f0037..2aa649844e5 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -40,6 +40,48 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 if(user.combat_mode) return ..(M, user) + +/obj/item/balloon_mallet + name = "balloon mallet" + desc = "It's a mallet, a weapon known for being heavy, but made from notoriously light balloons. Air inside removes any force from the swings. It'd be quite embarrassing to get hit by this." + icon = 'icons/obj/weapons/hammer.dmi' + icon_state = "balloon_mallet" + inhand_icon_state = "balloon_mallet" + lefthand_file = 'icons/mob/inhands/weapons/hammers_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/hammers_righthand.dmi' + siemens_coefficient = 0 + force = 1 + throw_speed = 1 + throwforce = 1 + throw_range = 1 + w_class = WEIGHT_CLASS_HUGE + attack_verb_continuous = list("mallets", "smoother") + attack_verb_simple = list("mallet", "smoother") + max_integrity = 20 + armor_type = /datum/armor/item_banhammer + resistance_flags = FIRE_PROOF + +/obj/item/balloon_mallet/examine(mob/user) + . = ..() + if(HAS_TRAIT(user,TRAIT_BALLOON_SUTRA)) + . = "A sacred weapon of the higher castes from the clown planet, used to strike fear into the hearts of their foes. Wield it with care." + +/obj/item/balloon_mallet/attack(mob/living/target, mob/living/user) + playsound(loc, 'sound/creatures/clown/hehe.ogg', 20) + if (!isliving(target)) + return + switch(target.mob_mood.sanity) + if (SANITY_INSANE to SANITY_CRAZY) + force = 8 + if (SANITY_UNSTABLE to SANITY_DISTURBED) + force = 4 + target.add_mood_event("humiliated", /datum/mood_event/mallet_humiliation) + if (SANITY_NEUTRAL to SANITY_GREAT) + target.add_mood_event("humiliated", /datum/mood_event/mallet_humiliation) + + if(user.combat_mode) + return ..(target, user) + /obj/item/sord name = "\improper SORD" desc = "This thing is so unspeakably shitty you are having a hard time even holding it." diff --git a/code/game/objects/items_reskin.dm b/code/game/objects/items_reskin.dm new file mode 100644 index 00000000000..1a7c27e098d --- /dev/null +++ b/code/game/objects/items_reskin.dm @@ -0,0 +1,57 @@ +/// Called when alt clicked and the item has unique reskin options +/obj/item/proc/on_click_alt_reskin(datum/source, mob/user) + SIGNAL_HANDLER + + if(!user.can_perform_action(src, NEED_DEXTERITY)) + return NONE + + if(!(obj_flags & INFINITE_RESKIN) && current_skin) + return NONE + + INVOKE_ASYNC(src, PROC_REF(reskin_obj), user) + return CLICK_ACTION_SUCCESS + + +/** + * Reskins object based on a user's choice + * + * Arguments: + * * M The mob choosing a reskin option + */ +/obj/item/proc/reskin_obj(mob/user) + if(!LAZYLEN(unique_reskin)) + return + + var/list/items = list() + for(var/reskin_option in unique_reskin) + var/image/item_image = image(icon = src.icon, icon_state = unique_reskin[reskin_option]) + items += list("[reskin_option]" = item_image) + sort_list(items) + + var/pick = show_radial_menu(user, src, items, custom_check = CALLBACK(src, PROC_REF(check_reskin_menu), user), radius = 38, require_near = TRUE) + if(!pick) + return + if(!unique_reskin[pick]) + return + current_skin = pick + icon_state = unique_reskin[pick] + to_chat(user, "[src] is now skinned as '[pick].'") + SEND_SIGNAL(src, COMSIG_OBJ_RESKIN, user, pick) + + +/** + * Checks if we are allowed to interact with a radial menu for reskins + * + * Arguments: + * * user The mob interacting with the menu + */ +/obj/item/proc/check_reskin_menu(mob/user) + if(QDELETED(src)) + return FALSE + if(!(obj_flags & INFINITE_RESKIN) && current_skin) + return FALSE + if(!istype(user)) + return FALSE + if(user.incapacitated()) + return FALSE + return TRUE diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 4f22a5e256b..f6fee49af7f 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -169,9 +169,9 @@ /** * The interminate proc between deconstruct() & atom_deconstruct(). By default this delegates deconstruction to - * atom_deconstruct if NO_DECONSTRUCTION is absent but subtypes can override this to handle NO_DECONSTRUCTION in their + * atom_deconstruct if NO_DEBRIS_AFTER_DECONSTRUCTION is absent but subtypes can override this to handle NO_DEBRIS_AFTER_DECONSTRUCTION in their * own unique way. Override this if for example you want to dump out important content like mobs from the - * atom before deconstruction regardless if NO_DECONSTRUCTION is present or not + * atom before deconstruction regardless if NO_DEBRIS_AFTER_DECONSTRUCTION is present or not * Arguments * * * disassembled - TRUE means we cleanly took this atom apart using tools. FALSE means this was destroyed in a violent way @@ -179,7 +179,7 @@ /obj/proc/handle_deconstruct(disassembled = TRUE) SHOULD_CALL_PARENT(FALSE) - if(!(obj_flags & NO_DECONSTRUCTION)) + if(!(obj_flags & NO_DEBRIS_AFTER_DECONSTRUCTION)) atom_deconstruct(disassembled) /** diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index d84fc46de43..bfdd0f71426 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -27,9 +27,6 @@ /// A multiplier to an objecet's force when used against a stucture, vechicle, machine, or robot. var/demolition_mod = 1 - var/current_skin //Has the item been reskinned? - var/list/unique_reskin //List of options to reskin. - /// Custom fire overlay icon, will just use the default overlay if this is null var/custom_fire_overlay /// Particles this obj uses when burning, if any @@ -117,54 +114,6 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag) else return null -/obj/proc/updateUsrDialog() - if(!(obj_flags & IN_USE)) - return - - var/is_in_use = FALSE - var/list/nearby = viewers(1, src) - for(var/mob/M in nearby) - if ((M.client && M.machine == src)) - is_in_use = TRUE - ui_interact(M) - if(issilicon(usr) || isAdminGhostAI(usr)) - if (!(usr in nearby)) - if (usr.client && usr.machine == src) // && M.machine == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh. - is_in_use = TRUE - ui_interact(usr) - - // check for TK users - - if(ishuman(usr)) - var/mob/living/carbon/human/H = usr - if(!(usr in nearby)) - if(usr.client && usr.machine == src) - if(H.dna.check_mutation(/datum/mutation/human/telekinesis)) - is_in_use = TRUE - ui_interact(usr) - if (is_in_use) - obj_flags |= IN_USE - else - obj_flags &= ~IN_USE - -/obj/proc/updateDialog(update_viewers = TRUE,update_ais = TRUE) - // Check that people are actually using the machine. If not, don't update anymore. - if(obj_flags & IN_USE) - var/is_in_use = FALSE - if(update_viewers) - for(var/mob/M in viewers(1, src)) - if ((M.client && M.machine == src)) - is_in_use = TRUE - src.interact(M) - var/ai_in_use = FALSE - if(update_ais) - ai_in_use = AutoUpdateAI(src) - - if(update_viewers && update_ais) //State change is sure only if we check both - if(!ai_in_use && !is_in_use) - obj_flags &= ~IN_USE - - /obj/attack_ghost(mob/user) . = ..() if(.) @@ -172,33 +121,6 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag) SEND_SIGNAL(src, COMSIG_ATOM_UI_INTERACT, user) ui_interact(user) -/mob/proc/unset_machine() - SIGNAL_HANDLER - if(!machine) - return - UnregisterSignal(machine, COMSIG_QDELETING) - machine.on_unset_machine(src) - machine = null - -//called when the user unsets the machine. -/atom/movable/proc/on_unset_machine(mob/user) - return - -/mob/proc/set_machine(obj/O) - if(QDELETED(src) || QDELETED(O)) - return - if(machine) - unset_machine() - machine = O - RegisterSignal(O, COMSIG_QDELETING, PROC_REF(unset_machine)) - if(istype(O)) - O.obj_flags |= IN_USE - -/obj/item/proc/updateSelfDialog() - var/mob/M = src.loc - if(istype(M) && M.client && M.machine == src) - src.attack_self(M) - /obj/singularity_pull(S, current_size) ..() if(move_resist == INFINITY) @@ -209,9 +131,6 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag) /obj/get_dumping_location() return get_turf(src) -/obj/proc/check_uplink_validity() - return 1 - /obj/vv_get_dropdown() . = ..() VV_DROPDOWN_OPTION("", "---") @@ -225,9 +144,7 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag) return if(href_list[VV_HK_OSAY]) - if(!check_rights(R_FUN, FALSE)) - return - usr.client.object_say(src) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/object_say, src) if(href_list[VV_HK_MASS_DEL_TYPE]) if(!check_rights(R_DEBUG|R_SERVER)) @@ -272,56 +189,7 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag) . += span_notice(desc_controls) if(obj_flags & UNIQUE_RENAME) . += span_notice("Use a pen on it to rename it or change its description.") - if(unique_reskin && (!current_skin || (obj_flags & INFINITE_RESKIN))) - . += span_notice("Alt-click it to reskin it.") -/obj/AltClick(mob/user) - . = ..() - if(unique_reskin && (!current_skin || (obj_flags & INFINITE_RESKIN)) && user.can_perform_action(src, NEED_DEXTERITY)) - reskin_obj(user) - -/** - * Reskins object based on a user's choice - * - * Arguments: - * * M The mob choosing a reskin option - */ -/obj/proc/reskin_obj(mob/user) - if(!LAZYLEN(unique_reskin)) - return - - var/list/items = list() - for(var/reskin_option in unique_reskin) - var/image/item_image = image(icon = src.icon, icon_state = unique_reskin[reskin_option]) - items += list("[reskin_option]" = item_image) - sort_list(items) - - var/pick = show_radial_menu(user, src, items, custom_check = CALLBACK(src, PROC_REF(check_reskin_menu), user), radius = 38, require_near = TRUE) - if(!pick) - return - if(!unique_reskin[pick]) - return - current_skin = pick - icon_state = unique_reskin[pick] - to_chat(user, "[src] is now skinned as '[pick].'") - SEND_SIGNAL(src, COMSIG_OBJ_RESKIN, user, pick) - -/** - * Checks if we are allowed to interact with a radial menu for reskins - * - * Arguments: - * * user The mob interacting with the menu - */ -/obj/proc/check_reskin_menu(mob/user) - if(QDELETED(src)) - return FALSE - if(!(obj_flags & INFINITE_RESKIN) && current_skin) - return FALSE - if(!istype(user)) - return FALSE - if(user.incapacitated()) - return FALSE - return TRUE /obj/analyzer_act(mob/living/user, obj/item/analyzer/tool) if(atmos_scan(user=user, target=src, silent=FALSE)) @@ -333,6 +201,7 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag) // Should move all contained objects to it's location. /obj/proc/dump_contents() + SHOULD_CALL_PARENT(FALSE) CRASH("Unimplemented.") /obj/handle_ricochet(obj/projectile/P) diff --git a/code/game/objects/structures/beds_chairs/alien_nest.dm b/code/game/objects/structures/beds_chairs/alien_nest.dm index 1654cecff45..77759c9e309 100644 --- a/code/game/objects/structures/beds_chairs/alien_nest.dm +++ b/code/game/objects/structures/beds_chairs/alien_nest.dm @@ -24,37 +24,39 @@ /obj/structure/bed/nest/wrench_act_secondary(mob/living/user, obj/item/weapon) return ITEM_INTERACT_BLOCKING -/obj/structure/bed/nest/user_unbuckle_mob(mob/living/buckled_mob, mob/living/user) - if(has_buckled_mobs()) - for(var/buck in buckled_mobs) //breaking a nest releases all the buckled mobs, because the nest isn't holding them down anymore - var/mob/living/M = buck - if(user.get_organ_by_type(/obj/item/organ/internal/alien/plasmavessel)) - unbuckle_mob(M) - add_fingerprint(user) - return +/obj/structure/bed/nest/user_unbuckle_mob(mob/living/captive, mob/living/hero) + if(!length(buckled_mobs)) + return - if(M != user) - M.visible_message(span_notice("[user.name] pulls [M.name] free from the sticky nest!"),\ - span_notice("[user.name] pulls you free from the gelatinous resin."),\ - span_hear("You hear squelching...")) - else - M.visible_message(span_warning("[M.name] struggles to break free from the gelatinous resin!"),\ - span_notice("You struggle to break free from the gelatinous resin... (Stay still for about a minute and a half.)"),\ - span_hear("You hear squelching...")) - if(!do_after(M, 100 SECONDS, target = src)) - if(M?.buckled) - to_chat(M, span_warning("You fail to unbuckle yourself!")) - return - if(!M.buckled) - return - M.visible_message(span_warning("[M.name] breaks free from the gelatinous resin!"),\ - span_notice("You break free from the gelatinous resin!"),\ - span_hear("You hear squelching...")) + if(hero.get_organ_by_type(/obj/item/organ/internal/alien/plasmavessel)) + unbuckle_mob(captive) + add_fingerprint(hero) + return + if(captive != hero) + captive.visible_message(span_notice("[hero.name] pulls [captive.name] free from the sticky nest!"), + span_notice("[hero.name] pulls you free from the gelatinous resin."), + span_hear("You hear squelching...")) + unbuckle_mob(captive) + add_fingerprint(hero) + return + + captive.visible_message(span_warning("[captive.name] struggles to break free from the gelatinous resin!"), + span_notice("You struggle to break free from the gelatinous resin... (Stay still for about a minute and a half.)"), + span_hear("You hear squelching...")) - unbuckle_mob(M) - add_fingerprint(user) + if(!do_after(captive, 100 SECONDS, target = src, hidden = TRUE)) + if(captive.buckled) + to_chat(captive, span_warning("You fail to unbuckle yourself!")) + return + + captive.visible_message(span_warning("[captive.name] breaks free from the gelatinous resin!"), + span_notice("You break free from the gelatinous resin!"), + span_hear("You hear squelching...")) + + unbuckle_mob(captive) + add_fingerprint(hero) /obj/structure/bed/nest/user_buckle_mob(mob/living/M, mob/user, check_loc = TRUE) if ( !ismob(M) || (get_dist(src, user) > 1) || (M.loc != src.loc) || user.incapacitated() || M.buckled ) diff --git a/code/game/objects/structures/beds_chairs/bed.dm b/code/game/objects/structures/beds_chairs/bed.dm index 5c5fac60eaa..0e3845d2efa 100644 --- a/code/game/objects/structures/beds_chairs/bed.dm +++ b/code/game/objects/structures/beds_chairs/bed.dm @@ -110,17 +110,14 @@ if(!isnull(foldable_type)) . += span_notice("You can fold it up with a Right-click.") -/obj/structure/bed/medical/AltClick(mob/user) - . = ..() - if(!can_interact(user)) - return - +/obj/structure/bed/medical/click_alt(mob/user) if(has_buckled_mobs() && (user in buckled_mobs)) - return + return CLICK_ACTION_BLOCKING anchored = !anchored balloon_alert(user, "brakes [anchored ? "applied" : "released"]") update_appearance() + return CLICK_ACTION_SUCCESS /obj/structure/bed/medical/post_buckle_mob(mob/living/buckled) . = ..() diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm index 0808c306ddb..6e218c56b82 100644 --- a/code/game/objects/structures/beds_chairs/chair.dm +++ b/code/game/objects/structures/beds_chairs/chair.dm @@ -57,8 +57,6 @@ return . = ..() -/obj/structure/chair/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation ///allows each chair to request the electrified_buckle component with overlays that dont look ridiculous /obj/structure/chair/proc/electrify_self(obj/item/assembly/shock_kit/input_shock_kit, mob/user, list/overlays_from_child_procs) @@ -447,6 +445,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0) buildstacktype = /obj/item/stack/sheet/bronze buildstackamount = 1 item_chair = null + interaction_flags_click = NEED_DEXTERITY + /// Total rotations made var/turns = 0 /obj/structure/chair/bronze/Initialize(mapload) @@ -464,10 +464,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0) if(turns >= 8) STOP_PROCESSING(SSfastprocess, src) -/obj/structure/chair/bronze/AltClick(mob/user) +/obj/structure/chair/bronze/click_alt(mob/user) turns = 0 - if(!user.can_perform_action(src, NEED_DEXTERITY)) - return if(!(datum_flags & DF_ISPROCESSING)) user.visible_message(span_notice("[user] spins [src] around, and the last vestiges of Ratvarian technology keeps it spinning FOREVER."), \ span_notice("Automated spinny chairs. The pinnacle of ancient Ratvarian technology.")) @@ -476,6 +474,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0) user.visible_message(span_notice("[user] stops [src]'s uncontrollable spinning."), \ span_notice("You grab [src] and stop its wild spinning.")) STOP_PROCESSING(SSfastprocess, src) + return CLICK_ACTION_SUCCESS /obj/structure/chair/mime name = "invisible chair" @@ -484,11 +483,11 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0) icon_state = null buildstacktype = null item_chair = null - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION + obj_flags = parent_type::obj_flags | NO_DEBRIS_AFTER_DECONSTRUCTION alpha = 0 /obj/structure/chair/mime/wrench_act_secondary(mob/living/user, obj/item/weapon) - return ITEM_INTERACT_BLOCKING + return NONE /obj/structure/chair/mime/post_buckle_mob(mob/living/M) M.pixel_y += 5 diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index 108ca3fe9b8..8b4fef65293 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -20,6 +20,7 @@ LINEN BINS w_class = WEIGHT_CLASS_TINY resistance_flags = FLAMMABLE dying_key = DYE_REGISTRY_BEDSHEET + interaction_flags_click = NEED_DEXTERITY dog_fashion = /datum/dog_fashion/head/ghost /// Custom nouns to act as the subject of dreams @@ -133,11 +134,9 @@ LINEN BINS else return ..() -/obj/item/bedsheet/AltClick(mob/living/user) - // double check the canUseTopic args to make sure it's correct - if(!istype(user) || !user.can_perform_action(src, NEED_DEXTERITY)) - return +/obj/item/bedsheet/click_alt(mob/living/user) dir = REVERSE_DIR(dir) + return CLICK_ACTION_SUCCESS /obj/item/bedsheet/blue icon_state = "sheetblue" diff --git a/code/game/objects/structures/bonfire.dm b/code/game/objects/structures/bonfire.dm index 02f611eb4e3..a26a2f92784 100644 --- a/code/game/objects/structures/bonfire.dm +++ b/code/game/objects/structures/bonfire.dm @@ -191,7 +191,6 @@ // Late init so that we can wait for air to exist in lazyloaded templates /obj/structure/bonfire/prelit/LateInitialize() - . = ..() start_burning() #undef BONFIRE_FIRE_STACK_STRENGTH diff --git a/code/game/objects/structures/broken_flooring.dm b/code/game/objects/structures/broken_flooring.dm index 3d1fa986505..9b2e4729080 100644 --- a/code/game/objects/structures/broken_flooring.dm +++ b/code/game/objects/structures/broken_flooring.dm @@ -16,7 +16,6 @@ return INITIALIZE_HINT_LATELOAD /obj/structure/broken_flooring/LateInitialize() - . = ..() var/turf/turf = get_turf(src) if(!isplatingturf(turf) && !always_floorplane) // Render as trash if not on plating plane = GAME_PLANE diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 3eb29fc1526..acbd7bfa395 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -163,7 +163,6 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) update_appearance() /obj/structure/closet/LateInitialize() - . = ..() if(!opened && is_maploaded) take_contents() @@ -581,7 +580,11 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) else return open(user) -/obj/structure/closet/atom_deconstruct(disassembled = TRUE) +/obj/structure/closet/handle_deconstruct(disassembled) + dump_contents() + if(obj_flags & NO_DEBRIS_AFTER_DECONSTRUCTION) + return + if(ispath(material_drop) && material_drop_amount) new material_drop(loc, material_drop_amount) if (secure) @@ -593,7 +596,6 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) electronics.accesses = req_access if(card_reader_installed) new /obj/item/stock_parts/card_reader(drop_location()) - dump_contents() /obj/structure/closet/atom_break(damage_flag) . = ..() diff --git a/code/game/objects/structures/crates_lockers/closets/bodybag.dm b/code/game/objects/structures/crates_lockers/closets/bodybag.dm index bfed8bea979..38482fcfd9b 100644 --- a/code/game/objects/structures/crates_lockers/closets/bodybag.dm +++ b/code/game/objects/structures/crates_lockers/closets/bodybag.dm @@ -171,7 +171,7 @@ if(A_is_item.w_class < max_weight_of_contents) continue max_weight_of_contents = A_is_item.w_class - folding_bodybag.w_class = max_weight_of_contents + folding_bodybag.update_weight_class(max_weight_of_contents) the_folder.put_in_hands(folding_bodybag) /// Environmental bags. They protect against bad weather. diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm index 679e31f9295..182c93b90df 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm @@ -27,7 +27,7 @@ . = ..() // Traitor steal objective - new /obj/item/areaeditor/blueprints(src) + new /obj/item/blueprints(src) new /obj/item/pipe_dispenser/bluespace(src) // SKYRAT EDIT -- BLUESPACE RPD -- ORIGINAL: new /obj/item/pipe_dispenser(src) /obj/structure/closet/secure_closet/engineering_electrical diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 0154015fb0d..394dc0c945e 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -46,20 +46,20 @@ var/static/list/crate_paint_jobs if(isnull(crate_paint_jobs)) crate_paint_jobs = list( - "Internals" = list("icon_state" = "o2crate"), - "Medical" = list("icon_state" = "medical"), - "Medical Plus" = list("icon_state" = "medicalcrate"), - "Radiation" = list("icon_state" = "radiation"), - "Hydrophonics" = list("icon_state" = "hydrocrate"), - "Science" = list("icon_state" = "scicrate"), - "Robotics" = list("icon_state" = "robo"), - "Solar" = list("icon_state" = "engi_e_crate"), - "Engineering" = list("icon_state" = "engi_crate"), - "Atmospherics" = list("icon_state" = "atmos"), - "Cargo" = list("icon_state" = "cargo"), - "Mining" = list("icon_state" = "mining"), - "Command" = list("icon_state" = "centcom") - ) + "Internals" = list("icon_state" = "o2crate"), + "Medical" = list("icon_state" = "medical"), + "Medical Plus" = list("icon_state" = "medicalcrate"), + "Radiation" = list("icon_state" = "radiation"), + "Hydrophonics" = list("icon_state" = "hydrocrate"), + "Science" = list("icon_state" = "scicrate"), + "Robotics" = list("icon_state" = "robo"), + "Solar" = list("icon_state" = "engi_e_crate"), + "Engineering" = list("icon_state" = "engi_crate"), + "Atmospherics" = list("icon_state" = "atmos"), + "Cargo" = list("icon_state" = "cargo"), + "Mining" = list("icon_state" = "mining"), + "Command" = list("icon_state" = "centcom"), + ) if(paint_jobs) paint_jobs = crate_paint_jobs diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index ae7cd5654ba..faebf85265c 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -451,8 +451,8 @@ ui.open() /obj/item/key/displaycase - name = "display case key" - desc = "The key to the curator's display cases." + name = "curator key" + desc = "The key to the curator's display cases and arcade cabinets." /obj/item/showpiece_dummy name = "holographic replica" diff --git a/code/game/objects/structures/divine.dm b/code/game/objects/structures/divine.dm index ef9f650e42a..6114a20158c 100644 --- a/code/game/objects/structures/divine.dm +++ b/code/game/objects/structures/divine.dm @@ -7,19 +7,17 @@ density = FALSE can_buckle = 1 -/obj/structure/sacrificealtar/AltClick(mob/living/user) - ..() - if(!istype(user) || !user.can_perform_action(src)) - return +/obj/structure/sacrificealtar/click_alt(mob/living/user) if(!has_buckled_mobs()) - return + return CLICK_ACTION_BLOCKING var/mob/living/L = locate() in buckled_mobs if(!L) - return + return CLICK_ACTION_BLOCKING to_chat(user, span_notice("Invoking the sacred ritual, you sacrifice [L].")) L.investigate_log("has been sacrificially gibbed on an altar.", INVESTIGATE_DEATHS) L.gib(DROP_ALL_REMAINS) message_admins("[ADMIN_LOOKUPFLW(user)] has sacrificed [key_name_admin(L)] on the sacrificial altar at [AREACOORD(src)].") + return CLICK_ACTION_SUCCESS /obj/structure/healingfountain name = "healing fountain" diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index e9f9eb5d11e..cace64a7101 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -91,9 +91,9 @@ qdel(src) return T -/obj/structure/falsewall/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) +/obj/structure/falsewall/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(!opening || !tool.tool_behaviour) - return ..() + return NONE to_chat(user, span_warning("You must wait until the door has stopped moving!")) return ITEM_INTERACT_BLOCKING diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index a0ef37aa0b3..13c0fe39ecd 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -453,7 +453,6 @@ icon_state = "pinepresents" desc = "A wondrous decorated Christmas tree. It has presents!" resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF //protected by the christmas spirit - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION var/gift_type = /obj/item/gift/anything var/unlimited = FALSE var/static/list/took_presents //shared between all xmas trees diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm index 039735dc36f..7f3e4195810 100644 --- a/code/game/objects/structures/kitchen_spike.dm +++ b/code/game/objects/structures/kitchen_spike.dm @@ -143,7 +143,7 @@ span_notice("You struggle to break free from [src], exacerbating your wounds! (Stay still for two minutes.)"),\ span_hear("You hear a wet squishing noise..")) buckled_mob.adjustBruteLoss(30) - if(!do_after(buckled_mob, 2 MINUTES, target = src)) + if(!do_after(buckled_mob, 2 MINUTES, target = src, hidden = TRUE)) if(buckled_mob?.buckled) to_chat(buckled_mob, span_warning("You fail to free yourself!")) return diff --git a/code/game/objects/structures/lavaland/geyser.dm b/code/game/objects/structures/lavaland/geyser.dm index ed6602cb513..7ef40423e0d 100644 --- a/code/game/objects/structures/lavaland/geyser.dm +++ b/code/game/objects/structures/lavaland/geyser.dm @@ -167,14 +167,12 @@ playsound(src, 'sound/machines/click.ogg', 10, TRUE) -/obj/item/plunger/AltClick(mob/user) - if(!istype(user) || !user.can_perform_action(src)) - return - +/obj/item/plunger/click_alt(mob/user) var/new_layer = tgui_input_list(user, "Select a layer", "Layer", GLOB.plumbing_layers) - if(isnull(new_layer)) - return + if(isnull(new_layer) || !user.can_perform_action(src)) + return CLICK_ACTION_BLOCKING target_layer = GLOB.plumbing_layers[new_layer] + return CLICK_ACTION_SUCCESS ///A faster reinforced plunger /obj/item/plunger/reinforced diff --git a/code/game/objects/structures/lavaland/gulag_vent.dm b/code/game/objects/structures/lavaland/gulag_vent.dm new file mode 100644 index 00000000000..aa13a1621d8 --- /dev/null +++ b/code/game/objects/structures/lavaland/gulag_vent.dm @@ -0,0 +1,42 @@ +/** + * A boulder-spawning structure superficially similar to an ore vent which doesnt share any of its behaviour + * Prisoners can haul boulders up out of it in case the actual mining area is totally spent + */ +/obj/structure/gulag_vent + name = "work pit" + desc = "A timeworn shaft, almost totally mined out. With a bit of effort you might be able to haul something up." + icon = 'icons/obj/mining_zones/terrain.dmi' + icon_state = "ore_vent_active" + move_resist = MOVE_FORCE_EXTREMELY_STRONG + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF //This thing will take a beating. + interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_REQUIRES_DEXTERITY + anchored = TRUE + density = TRUE + /// What kind of rock we got in there? + var/spawned_boulder = /obj/item/boulder/gulag + /// Prevents multiple people from hauling at a time + var/occupied = FALSE + +/obj/structure/gulag_vent/ice + icon_state = "ore_vent_ice_active" + +/obj/structure/gulag_vent/interact(mob/user) + . = ..() + if (!isliving(user)) + return + if (occupied) + balloon_alert(user, "occupied!") + return + var/mob/living/living_user = user + occupied = TRUE + living_user.balloon_alert_to_viewers("hauling...") + var/succeeded = do_after(living_user, 8 SECONDS, src) + occupied = FALSE + if (!succeeded) + return + living_user.mind?.adjust_experience(/datum/skill/fitness, 10) + living_user.apply_status_effect(/datum/status_effect/exercised) + new spawned_boulder(get_turf(living_user)) + living_user.visible_message(span_notice("[living_user] hauls a boulder out of [src].")) + living_user.apply_damage(120, STAMINA) + playsound(src, 'sound/weapons/genhit.ogg', vol = 50, vary = TRUE) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index de15b16981b..cc6222f4ac0 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -170,6 +170,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an icon_state = "morgue1" base_icon_state = "morgue" dir = EAST + interaction_flags_click = ALLOW_SILICON_REACH|ALLOW_RESTING connected = /obj/structure/tray/m_tray @@ -190,13 +191,11 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an /// Minimum temperature of the internal air mixture var/minimum_temperature = T0C - 60 - /obj/structure/bodycontainer/morgue/Initialize(mapload) ..() return INITIALIZE_HINT_LATELOAD /obj/structure/bodycontainer/morgue/LateInitialize() - . = ..() var/datum/gas_mixture/external_air = loc.return_air() if(external_air) internal_air = external_air.copy() @@ -301,12 +300,10 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an . = ..() . += span_notice("The speaker is [beeper ? "enabled" : "disabled"]. Alt-click to toggle it.") -/obj/structure/bodycontainer/morgue/AltClick(mob/user) - ..() - if(!user.can_perform_action(src, (ALLOW_SILICON_REACH|ALLOW_RESTING))) - return +/obj/structure/bodycontainer/morgue/click_alt(mob/user) beeper = !beeper to_chat(user, span_notice("You turn the speaker function [beeper ? "on" : "off"].")) + return CLICK_ACTION_SUCCESS /obj/structure/bodycontainer/morgue/emag_act(mob/user, obj/item/card/emag/emag_card) if(obj_flags & EMAGGED) diff --git a/code/game/objects/structures/plaques/static_plaques.dm b/code/game/objects/structures/plaques/static_plaques.dm index 2fe784c6eba..ffd2982ccc6 100644 --- a/code/game/objects/structures/plaques/static_plaques.dm +++ b/code/game/objects/structures/plaques/static_plaques.dm @@ -35,8 +35,7 @@ . = ..() return INITIALIZE_HINT_LATELOAD -/obj/structure/plaque/static_plaque/tram/LateInitialize(mapload) - . = ..() +/obj/structure/plaque/static_plaque/tram/LateInitialize() link_tram() set_tram_serial() diff --git a/code/game/objects/structures/railings.dm b/code/game/objects/structures/railings.dm index 95cf4fc58e5..2651684e39b 100644 --- a/code/game/objects/structures/railings.dm +++ b/code/game/objects/structures/railings.dm @@ -88,8 +88,6 @@ to_chat(user, span_warning("[src] is already in good condition!")) return -/obj/structure/railing/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation /obj/structure/railing/wirecutter_act(mob/living/user, obj/item/I) . = ..() diff --git a/code/game/objects/structures/reflector.dm b/code/game/objects/structures/reflector.dm index 0d6799b0583..0700f19818a 100644 --- a/code/game/objects/structures/reflector.dm +++ b/code/game/objects/structures/reflector.dm @@ -79,10 +79,10 @@ P.decayedRange = max(P.decayedRange--, 0) return BULLET_ACT_FORCE_PIERCE -/obj/structure/reflector/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) +/obj/structure/reflector/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(admin && tool.tool_behaviour) return ITEM_INTERACT_BLOCKING - return ..() + return NONE /obj/structure/reflector/screwdriver_act(mob/living/user, obj/item/tool) can_rotate = !can_rotate diff --git a/code/game/objects/structures/shower.dm b/code/game/objects/structures/shower.dm index 298c6fd2294..c37be03652c 100644 --- a/code/game/objects/structures/shower.dm +++ b/code/game/objects/structures/shower.dm @@ -373,8 +373,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/shower, (-16)) deconstruct() return TRUE -/obj/structure/showerframe/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation /obj/effect/mist name = "mist" diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 234abcbeb39..29c93fcda25 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -220,6 +220,7 @@ to_chat(user, span_notice("You start deconstructing [src]...")) if(tool.use_tool(src, user, 4 SECONDS, volume=50)) playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE) + frame = null deconstruct(TRUE) return ITEM_INTERACT_SUCCESS @@ -304,7 +305,11 @@ else for(var/datum/material/mat in custom_materials) new mat.sheet_type(target_turf, FLOOR(custom_materials[mat] / SHEET_MATERIAL_AMOUNT, 1)) - new framestack(target_turf, framestackamount) + + if(frame) + new frame(target_turf) + else + new framestack(get_turf(src), framestackamount) /obj/structure/table/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) if(the_rcd.mode == RCD_DECONSTRUCT) @@ -857,12 +862,12 @@ deconstruct(TRUE) return ITEM_INTERACT_SUCCESS -/obj/structure/rack/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) - . = ..() - if(. || (tool.item_flags & ABSTRACT) || user.combat_mode) - return . +/obj/structure/rack/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if((tool.item_flags & ABSTRACT) || user.combat_mode) + return NONE if(user.transferItemToLoc(tool, drop_location(), silent = FALSE)) return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING /obj/structure/rack/attack_paw(mob/living/user, list/modifiers) attack_hand(user, modifiers) diff --git a/code/game/objects/structures/training_machine.dm b/code/game/objects/structures/training_machine.dm index fd0d8bb0c8f..c2f4d3a18ae 100644 --- a/code/game/objects/structures/training_machine.dm +++ b/code/game/objects/structures/training_machine.dm @@ -20,6 +20,7 @@ can_buckle = TRUE buckle_lying = 0 max_integrity = 200 + interaction_flags_click = NEED_DEXTERITY|FORBID_TELEKINESIS_REACH|ALLOW_RESTING ///Is the machine moving? Setting this to FALSE will automatically call stop_moving() var/moving = FALSE ///The distance the machine is allowed to roam from its starting point @@ -174,21 +175,19 @@ attached_item.throw_at(destination, 4, 1) on_attached_delete() -/obj/structure/training_machine/AltClick(mob/user) - . = ..() - if(!user.can_perform_action(src, NEED_DEXTERITY|FORBID_TELEKINESIS_REACH|ALLOW_RESTING)) - return +/obj/structure/training_machine/click_alt(mob/user) if(has_buckled_mobs()) user_unbuckle_mob(buckled_mobs[1], user) - return + return CLICK_ACTION_SUCCESS if (!attached_item) - return + return NONE if (obj_flags & EMAGGED) to_chat(user, span_warning("The toolbox is somehow stuck on! It won't budge!")) - return + return CLICK_ACTION_BLOCKING to_chat(user, span_notice("You remove \the [attached_item] from the training device.")) remove_attached_item(user) playsound(src, SFX_RUSTLE, 50, TRUE) + return CLICK_ACTION_SUCCESS /** * Toggle the machine's movement @@ -396,12 +395,10 @@ if (!.) check_hit(hit_atom) -/obj/item/training_toolbox/AltClick(mob/user) - . = ..() - if(!can_interact(user)) - return +/obj/item/training_toolbox/click_alt(mob/user) to_chat(user, span_notice("You push the 'Lap' button on the toolbox's display.")) lap_hits = initial(lap_hits) + return CLICK_ACTION_SUCCESS /obj/item/training_toolbox/examine(mob/user) . = ..() diff --git a/code/game/objects/structures/transit_tubes/transit_tube_construction.dm b/code/game/objects/structures/transit_tubes/transit_tube_construction.dm index 44952801ec7..e6b0f30225c 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube_construction.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube_construction.dm @@ -51,8 +51,6 @@ qdel(src) return TRUE -/obj/structure/c_transit_tube/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation // transit tube station /obj/structure/c_transit_tube/station diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm index 0a56c6add69..3437e2a5ae0 100644 --- a/code/game/objects/structures/windoor_assembly.dm +++ b/code/game/objects/structures/windoor_assembly.dm @@ -327,8 +327,6 @@ qdel(src) -/obj/structure/windoor_assembly/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation //Flips the windoor assembly, determines whather the door opens to the left or the right /obj/structure/windoor_assembly/verb/flip() diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 89d04f46976..818e3c43499 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -188,11 +188,11 @@ return return ..() -/obj/structure/window/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) +/obj/structure/window/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(!can_be_reached(user)) return ITEM_INTERACT_SKIP_TO_ATTACK // Guess you get to hit it add_fingerprint(user) - return ..() + return NONE /obj/structure/window/welder_act(mob/living/user, obj/item/tool) if(atom_integrity >= max_integrity) @@ -277,8 +277,6 @@ add_fingerprint(user) return ..() -/obj/structure/window/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation /obj/structure/window/set_anchored(anchorvalue) ..() @@ -702,7 +700,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/window/reinforced/tinted/frosted/spaw /obj/structure/window/reinforced/fulltile name = "full tile reinforced window" - desc = "A full tile reinforced window" + desc = "A full tile window that is reinforced with metal rods." icon = 'icons/obj/smooth_structures/reinforced_window.dmi' //ICON OVERRIDDEN IN SKYRAT AESTHETICS - SEE MODULE icon_state = "reinforced_window-0" base_icon_state = "reinforced_window" @@ -792,10 +790,18 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/window/reinforced/tinted/frosted/spaw name = "hardened shuttle window" flags_1 = PREVENT_CLICK_UNDER_1 resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION -/obj/structure/window/reinforced/shuttle/indestructible/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - return FALSE +/obj/structure/window/reinforced/shuttle/indestructible/welder_act(mob/living/user, obj/item/tool) + return NONE + +/obj/structure/window/reinforced/shuttle/indestructible/screwdriver_act(mob/living/user, obj/item/tool) + return NONE + +/obj/structure/window/reinforced/shuttle/indestructible/wrench_act(mob/living/user, obj/item/tool) + return NONE + +/obj/structure/window/reinforced/shuttle/indestructible/crowbar_act(mob/living/user, obj/item/tool) + return NONE /obj/structure/window/reinforced/plasma/plastitanium name = "plastitanium window" diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index 1253d156a2c..60462cafbd1 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -96,6 +96,8 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( var/list/old_baseturfs = baseturfs var/old_type = type + var/datum/weakref/old_ref = weak_reference + weak_reference = null var/list/post_change_callbacks = list() SEND_SIGNAL(src, COMSIG_TURF_CHANGE, path, new_baseturfs, flags, post_change_callbacks) @@ -142,6 +144,8 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( lattice_underneath = old_lattice_underneath + new_turf.weak_reference = old_ref + if(SSlighting.initialized) // Space tiles should never have lighting objects if(!space_lit) diff --git a/code/game/turfs/open/floor/glass.dm b/code/game/turfs/open/floor/glass.dm index b1579da55f0..cece195aaf8 100644 --- a/code/game/turfs/open/floor/glass.dm +++ b/code/game/turfs/open/floor/glass.dm @@ -33,7 +33,6 @@ return INITIALIZE_HINT_LATELOAD /turf/open/floor/glass/LateInitialize() - . = ..() AddElement(/datum/element/turf_z_transparency) setup_glow() diff --git a/code/game/turfs/open/floor/plating.dm b/code/game/turfs/open/floor/plating.dm index 974042ce7c8..5bcd8a6a4a8 100644 --- a/code/game/turfs/open/floor/plating.dm +++ b/code/game/turfs/open/floor/plating.dm @@ -177,9 +177,8 @@ ScrapeAway(flags = CHANGETURF_INHERIT_AIR) return TRUE -/turf/open/floor/plating/foam/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) - SHOULD_CALL_PARENT(FALSE) - return NONE // Fuck you +/turf/open/floor/plating/foam/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + return user.combat_mode ? ITEM_INTERACT_SKIP_TO_ATTACK : ITEM_INTERACT_BLOCKING // Fuck you //reinforced plating deconstruction states #define PLATE_INTACT 0 diff --git a/code/game/turfs/open/openspace.dm b/code/game/turfs/open/openspace.dm index 24345611576..2006a3e6829 100644 --- a/code/game/turfs/open/openspace.dm +++ b/code/game/turfs/open/openspace.dm @@ -32,7 +32,6 @@ return INITIALIZE_HINT_LATELOAD /turf/open/openspace/LateInitialize() - . = ..() AddElement(/datum/element/turf_z_transparency) /turf/open/openspace/ChangeTurf(path, list/new_baseturfs, flags) @@ -188,7 +187,9 @@ if(!T) return if(T.turf_flags & NO_RUINS && protect_ruin) - ChangeTurf(replacement_turf, null, CHANGETURF_IGNORE_AIR) + var/turf/newturf = ChangeTurf(replacement_turf, null, CHANGETURF_IGNORE_AIR) + if(!isopenspaceturf(newturf)) // only openspace turfs should be returning INITIALIZE_HINT_LATELOAD + return INITIALIZE_HINT_NORMAL return if(!ismineralturf(T) || !drill_below) return diff --git a/code/game/turfs/open/space/space.dm b/code/game/turfs/open/space/space.dm index d404870e1c8..1bfe5c2e5e1 100644 --- a/code/game/turfs/open/space/space.dm +++ b/code/game/turfs/open/space/space.dm @@ -273,7 +273,6 @@ GLOBAL_LIST_EMPTY(starlight) return INITIALIZE_HINT_LATELOAD /turf/open/space/openspace/LateInitialize() - . = ..() AddElement(/datum/element/turf_z_transparency) /turf/open/space/openspace/Destroy() diff --git a/code/game/turfs/open/water.dm b/code/game/turfs/open/water.dm index debf5c0f6b1..55ca23beead 100644 --- a/code/game/turfs/open/water.dm +++ b/code/game/turfs/open/water.dm @@ -23,6 +23,7 @@ /turf/open/water/Initialize(mapload) . = ..() AddElement(/datum/element/immerse, icon, icon_state, "immerse", immerse_overlay_color) + AddElement(/datum/element/watery_tile) /turf/open/water/jungle diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 99aa63325ad..10b9a58b870 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -48,14 +48,9 @@ ////////////////////////////////////////////////////////////////////////////////////////////////ADMIN HELPER PROCS -/datum/admins/proc/spawn_atom(object as text) - set category = "Debug" - set desc = "(atom path) Spawn an atom" - set name = "Spawn" - - if(!check_rights(R_SPAWN) || !object) +ADMIN_VERB(spawn_atom, R_SPAWN, "Spawn", "Spawn an atom.", ADMIN_CATEGORY_DEBUG, object as text) + if(!object) return - var/list/preparsed = splittext(object,":") var/path = preparsed[1] var/amount = 1 @@ -65,7 +60,7 @@ var/chosen = pick_closest_path(path) if(!chosen) return - var/turf/T = get_turf(usr) + var/turf/T = get_turf(user.mob) if(ispath(chosen, /turf)) T.ChangeTurf(chosen) @@ -74,21 +69,14 @@ var/atom/A = new chosen(T) A.flags_1 |= ADMIN_SPAWNED_1 - log_admin("[key_name(usr)] spawned [amount] x [chosen] at [AREACOORD(usr)]") + log_admin("[key_name(user)] spawned [amount] x [chosen] at [AREACOORD(user.mob)]") BLACKBOX_LOG_ADMIN_VERB("Spawn Atom") -/datum/admins/proc/podspawn_atom(object as text) - set category = "Debug" - set desc = "(atom path) Spawn an atom via supply drop" - set name = "Podspawn" - - if(!check_rights(R_SPAWN)) - return - +ADMIN_VERB(spawn_atom_pod, R_SPAWN, "PodSpawn", "Spawn an atom via supply drop.", ADMIN_CATEGORY_DEBUG, object as text) var/chosen = pick_closest_path(object) if(!chosen) return - var/turf/target_turf = get_turf(usr) + var/turf/target_turf = get_turf(user.mob) if(ispath(chosen, /turf)) target_turf.ChangeTurf(chosen) @@ -101,25 +89,18 @@ var/atom/A = new chosen(pod) A.flags_1 |= ADMIN_SPAWNED_1 - log_admin("[key_name(usr)] pod-spawned [chosen] at [AREACOORD(usr)]") + log_admin("[key_name(user)] pod-spawned [chosen] at [AREACOORD(user.mob)]") BLACKBOX_LOG_ADMIN_VERB("Podspawn Atom") -/datum/admins/proc/spawn_cargo(object as text) - set category = "Debug" - set desc = "(atom path) Spawn a cargo crate" - set name = "Spawn Cargo" - - if(!check_rights(R_SPAWN)) - return - +ADMIN_VERB(spawn_cargo, R_SPAWN, "Spawn Cargo", "Spawn a cargo crate.", ADMIN_CATEGORY_DEBUG, object as text) var/chosen = pick_closest_path(object, make_types_fancy(subtypesof(/datum/supply_pack))) if(!chosen) return var/datum/supply_pack/S = new chosen S.admin_spawned = TRUE - S.generate(get_turf(usr)) + S.generate(get_turf(user.mob)) - log_admin("[key_name(usr)] spawned cargo pack [chosen] at [AREACOORD(usr)]") + log_admin("[key_name(user)] spawned cargo pack [chosen] at [AREACOORD(user.mob)]") BLACKBOX_LOG_ADMIN_VERB("Spawn Cargo") /datum/admins/proc/dynamic_mode_options(mob/user) @@ -246,10 +227,8 @@ log_admin(logged_message) message_admins(logged_message) -/datum/admins/proc/create_or_modify_area() - set category = "Debug" - set name = "Create or modify area" - create_area(usr) +ADMIN_VERB(create_or_modify_area, R_DEBUG, "Create Or Modify Area", "Create of modify an area. wow.", ADMIN_CATEGORY_DEBUG) + create_area(user.mob) //Kicks all the clients currently in the lobby. The second parameter (kick_only_afk) determins if an is_afk() check is ran, or if all clients are kicked //defaults to kicking everyone (afk + non afk clients in the lobby) diff --git a/code/modules/admin/admin_fax_panel.dm b/code/modules/admin/admin_fax_panel.dm index fe1f03d7d7e..8874b6f38eb 100644 --- a/code/modules/admin/admin_fax_panel.dm +++ b/code/modules/admin/admin_fax_panel.dm @@ -1,15 +1,6 @@ -/** - * If client have R_ADMIN flag, opens an admin fax panel. - */ -/client/proc/fax_panel() - set category = "Admin.Events" - set name = "Fax Panel" - - if(!check_rights(R_ADMIN)) - return - - var/datum/fax_panel_interface/ui = new(usr) - ui.ui_interact(usr) +ADMIN_VERB(fax_panel, R_ADMIN, "Fax Panel", "View and respond to faxes sent to CC.", ADMIN_CATEGORY_EVENTS) + var/datum/fax_panel_interface/ui = new /datum/fax_panel_interface(user.mob) + ui.ui_interact(user.mob) /// Admin Fax Panel. Tool for sending fax messages faster. /datum/fax_panel_interface @@ -97,15 +88,15 @@ switch(action) if("follow") - if(!isobserver(usr)) - usr.client?.admin_ghost() + if(!isobserver(ui.user)) + SSadmin_verbs.dynamic_invoke_verb(ui.user, /datum/admin_verb/admin_ghost) - usr.client?.admin_follow(action_fax) + ui.user.client?.admin_follow(action_fax) if("preview") // see saved variant if(!fax_paper) return - fax_paper.ui_interact(usr) + fax_paper.ui_interact(ui.user) if("save") // save paper if(params["paperName"]) @@ -129,7 +120,7 @@ if(stamp) fax_paper.add_stamp(stamp_class, params["stampX"], params["stampY"], params["stampAngle"], stamp) - fax_paper.update_static_data(usr) // OK, it's work, and update UI. + fax_paper.update_static_data(ui.user) // OK, it's work, and update UI. if("send") //copy @@ -137,9 +128,9 @@ our_fax.name = fax_paper.name //send action_fax.receive(our_fax, sending_fax_name) - message_admins("[key_name_admin(usr)] has sent a custom fax message to [action_fax.name][ADMIN_FLW(action_fax)][ADMIN_SHOW_PAPER(fax_paper)].") - log_admin("[key_name(usr)] has sent a custom fax message to [action_fax.name]") + message_admins("[key_name_admin(ui.user)] has sent a custom fax message to [action_fax.name][ADMIN_FLW(action_fax)][ADMIN_SHOW_PAPER(fax_paper)].") + log_admin("[key_name(ui.user)] has sent a custom fax message to [action_fax.name]") if("createPaper") - var/obj/item/paper/our_paper = fax_paper.copy(/obj/item/paper, usr.loc) + var/obj/item/paper/our_paper = fax_paper.copy(/obj/item/paper, ui.user.loc) our_paper.name = fax_paper.name diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm index 94ea182891f..edc3525bf2f 100644 --- a/code/modules/admin/admin_investigate.dm +++ b/code/modules/admin/admin_investigate.dm @@ -10,13 +10,8 @@ WRITE_FILE(F, "[time_stamp(format = "YYYY-MM-DD hh:mm:ss")] [REF(src)] ([x],[y],[z]) || [source] [message]
") -/client/proc/investigate_show() - set name = "Investigate" - set category = "Admin.Game" - if(!holder) - return - - var/list/investigates = list( +ADMIN_VERB(investigate_show, R_NONE, "Investigate", "Browse various detailed logs.", ADMIN_CATEGORY_GAME) + var/static/list/investigates = list( INVESTIGATE_ACCESSCHANGES, INVESTIGATE_ATMOS, INVESTIGATE_BOTANY, @@ -48,7 +43,7 @@ var/list/combined = sort_list(logs_present) + sort_list(logs_missing) - var/selected = tgui_input_list(src, "Investigate what?", "Investigation", combined) + var/selected = tgui_input_list(user, "Investigate what?", "Investigation", combined) if(isnull(selected)) return if(!(selected in combined) || selected == "---") @@ -62,6 +57,6 @@ var/F = file("[GLOB.log_directory]/[selected].html") if(!fexists(F)) - to_chat(src, span_danger("No [selected] logfile was found."), confidential = TRUE) + to_chat(user, span_danger("No [selected] logfile was found."), confidential = TRUE) return - src << browse(F,"window=investigate[selected];size=800x300") + user << browse(F,"window=investigate[selected];size=800x300") diff --git a/code/modules/admin/admin_pda_message.dm b/code/modules/admin/admin_pda_message.dm index 44ca86f893e..c1c4fef0b57 100644 --- a/code/modules/admin/admin_pda_message.dm +++ b/code/modules/admin/admin_pda_message.dm @@ -1,12 +1,6 @@ -///Allows an admin to send messages on PDA -/client/proc/message_pda() - set name = "PDA Message" - set category = "Admin.Events" - if(!holder || !check_rights(R_ADMIN)) - return - - holder.message_pda() +ADMIN_VERB(message_pda, R_ADMIN, "PDA Message", "Send a message to a user's PDA.", ADMIN_CATEGORY_EVENTS) + user.holder.message_pda() ///Opens up the PDA Message Panel /datum/admins/proc/message_pda() diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index c7ebfeab8f0..731de224f8d 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -1,505 +1,103 @@ -//admin verb groups - They can overlap if you so wish. Only one of each verb will exist in the verbs list regardless -//the procs are cause you can't put the comments in the GLOB var define -GLOBAL_LIST_INIT(admin_verbs_default, world.AVerbsDefault()) -GLOBAL_PROTECT(admin_verbs_default) -/world/proc/AVerbsDefault() - return list( - /client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/ - /client/proc/cmd_admin_pm_panel, /*admin-pm list*/ - /client/proc/cmd_admin_say, /*admin-only ooc chat*/ - /client/proc/deadmin, /*destroys our own admin datum so we can play as a regular player*/ - /client/proc/debugstatpanel, - /client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/ - /client/proc/dsay, /*talk in deadchat using our ckey/fakekey*/ - /client/proc/fix_air, /*resets air in designated radius to its default atmos composition*/ - /client/proc/hide_verbs, /*hides all our adminverbs*/ - /client/proc/investigate_show, /*various admintools for investigation. Such as a singulo grief-log*/ - /client/proc/mark_datum_mapview, - /client/proc/reestablish_db_connection, /*reattempt a connection to the database*/ - /client/proc/reload_admins, - /client/proc/requests, - /client/proc/secrets, - /client/proc/stop_sounds, - /client/proc/tag_datum_mapview, - - /client/proc/addbunkerbypass, /*SKYRAT EDIT ADDITION - PANICBUNKER*/ - /client/proc/cmd_loud_admin_say, /*admin-only chat except its annoying - SKYRAT EDIT ADDITION - ADMIN*/ - /client/proc/remove_liquid, /*SKYRAT EDIT ADDITION*/ - /client/proc/revokebunkerbypass, /*SKYRAT EDIT ADDITION - PANICBUNKER*/ - ) -GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin()) -GLOBAL_PROTECT(admin_verbs_admin) -/world/proc/AVerbsAdmin() - return list( -// Admin datums - /datum/admins/proc/access_news_network, /*allows access of newscasters*/ - /datum/admins/proc/announce, /*priority announce something to all clients.*/ - /datum/admins/proc/display_tags, - /datum/admins/proc/fishing_calculator, - /datum/admins/proc/known_alts_panel, - /datum/admins/proc/show_lag_switch_panel, - /datum/admins/proc/open_borgopanel, - /datum/admins/proc/open_shuttlepanel, /* Opens shuttle manipulator UI */ - /datum/admins/proc/paintings_manager, - /datum/admins/proc/set_admin_notice, /*announcement all clients see when joining the server.*/ - /datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/ - /datum/admins/proc/toggleenter, /*toggles whether people can join the current game*/ - /datum/admins/proc/toggleguests, /*toggles whether guests can join the current game*/ - /datum/admins/proc/toggleooc, /*toggles ooc on/off for everyone*/ - /datum/admins/proc/toggleoocdead, /*toggles ooc on/off for everyone who is dead*/ - /datum/admins/proc/trophy_manager, - /datum/admins/proc/view_all_circuits, - /datum/verbs/menu/Admin/verb/playerpanel, /* It isn't /datum/admin but it fits no less */ - /datum/admins/proc/change_shuttle_events, //allows us to change the shuttle events - /datum/admins/proc/reset_tram, //tram related admin actions -// Client procs - /client/proc/admin_call_shuttle, /*allows us to call the emergency shuttle*/ - /client/proc/admin_cancel_shuttle, /*allows us to cancel the emergency shuttle, sending it back to centcom*/ - /client/proc/admin_disable_shuttle, /*allows us to disable the emergency shuttle admin-wise so that it cannot be called*/ - /client/proc/admin_enable_shuttle, /*undoes the above*/ - /client/proc/admin_ghost, /*allows us to ghost/reenter body at will*/ - /client/proc/admin_hostile_environment, /*Allows admins to prevent the emergency shuttle from leaving, also lets admins clear hostile environments if theres one stuck*/ - /client/proc/centcom_podlauncher,/*Open a window to launch a Supplypod and configure it or it's contents*/ - /client/proc/check_ai_laws, /*shows AI and borg laws*/ - /client/proc/check_antagonists, /*shows all antags*/ - /client/proc/cmd_admin_check_contents, /*displays the contents of an instance*/ - /client/proc/cmd_admin_check_player_exp, /* shows players by playtime */ - /client/proc/cmd_admin_create_centcom_report, - /client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/ - /client/proc/cmd_admin_direct_narrate, /*send text directly to a player with no padding. Useful for narratives and fluff-text*/ - /client/proc/cmd_admin_headset_message, /*send a message to somebody through their headset as CentCom*/ - /client/proc/cmd_admin_local_narrate, /*sends text to all mobs within view of atom*/ - /client/proc/cmd_admin_subtle_message, /*send a message to somebody as a 'voice in their head'*/ - /client/proc/cmd_admin_world_narrate, /*sends text to all players with no padding*/ - /client/proc/cmd_change_command_name, - /client/proc/create_mob_worm, - /client/proc/fax_panel, /*send a paper to fax*/ - /client/proc/force_load_lazy_template, - /client/proc/game_panel, /*game panel, allows to change game-mode etc*/ - /client/proc/Getmob, /*teleports a mob to our location*/ - /client/proc/Getkey, /*teleports a mob with a certain ckey to our location*/ - /client/proc/getserverlogs, /*for accessing server logs*/ - /client/proc/getcurrentlogs, /*for accessing server logs for the current round*/ - /client/proc/ghost_pool_protection, /*opens a menu for toggling ghost roles*/ - /client/proc/invisimin, /*allows our mob to go invisible/visible*/ - /client/proc/jumptoarea, - /client/proc/jumptokey, /*allows us to jump to the location of a mob with a certain ckey*/ - /client/proc/jumptomob, /*allows us to jump to a specific mob*/ - /client/proc/jumptoturf, /*allows us to jump to a specific turf*/ - /client/proc/jumptocoord, /*we ghost and jump to a coordinate*/ - /client/proc/list_bombers, - /client/proc/list_dna, - /client/proc/list_fingerprints, - /client/proc/list_law_changes, - /client/proc/list_signalers, - /client/proc/manage_sect, /*manage chaplain religious sect*/ - /client/proc/message_pda, /*send a message to somebody on PDA*/ - /client/proc/respawn_character, - /client/proc/show_manifest, - /client/proc/toggle_AI_interact, /*toggle admin ability to interact with machines as an AI*/ - /client/proc/toggle_combo_hud, /* toggle display of the combination pizza antag and taco sci/med/eng hud */ - /client/proc/toggle_view_range, /*changes how far we can see*/ - /client/proc/cmd_admin_law_panel, - /client/proc/log_viewer_new, - /client/proc/player_ticket_history, - /datum/admins/proc/toggleaooc, /*Toggle Antag OOC - SKYRAT EDIT ADDITION*/ - /datum/admins/proc/toggledchat, /*SKYRAT EDIT ADDITION*/ - /datum/admins/proc/togglesooc, /*Toggle Security OOC - SKYRAT EDIT ADDITION*/ - /client/proc/admin_open_event_spawners_menu, /*EVENTS - SKYRAT EDIT ADDITION*/ - /client/proc/request_help, /*SKYRAT EDIT ADDITION*/ - /client/proc/view_opfors, /*OPFOR - SKYRAT EDIT ADDITION*/ - /client/proc/lorecaster_story_manager, /* SKYRAT EDIT ADDITION */ - ) -GLOBAL_LIST_INIT(admin_verbs_ban, list(/client/proc/unban_panel, /client/proc/ban_panel, /client/proc/stickybanpanel, /client/proc/library_control)) -GLOBAL_PROTECT(admin_verbs_ban) -GLOBAL_LIST_INIT(admin_verbs_sounds, list(/client/proc/play_local_sound, /client/proc/play_direct_mob_sound, /client/proc/play_sound, /client/proc/set_round_end_sound)) -GLOBAL_PROTECT(admin_verbs_sounds) -GLOBAL_LIST_INIT(admin_verbs_fun, list( -// Admin datums - /datum/admins/proc/station_traits_panel, -// Client procs - /client/proc/admin_away, - /client/proc/add_marked_mob_ability, - /client/proc/admin_change_sec_level, - /client/proc/cinematic, - /client/proc/cmd_admin_add_freeform_ai_law, - /client/proc/cmd_admin_gib_self, - /client/proc/cmd_select_equipment, - /client/proc/command_report_footnote, - /client/proc/delay_command_report, - /client/proc/drop_bomb, - /client/proc/drop_dynex_bomb, - /client/proc/forceEvent, - /client/proc/mass_zombie_cure, - /client/proc/mass_zombie_infection, - /client/proc/object_say, - /client/proc/polymorph_all, - /client/proc/remove_marked_mob_ability, - /client/proc/reset_ooc, - /client/proc/run_weather, - /client/proc/set_dynex_scale, - /client/proc/set_ooc, - /client/proc/show_tip, - /client/proc/smite, - /client/proc/summon_ert, - /client/proc/toggle_nuke, - /client/proc/toggle_random_events, - /client/proc/admin_change_title_screen, /*SKYRAT EDIT ADDITION*/ - /client/proc/change_title_screen_html, /*SKYRAT EDIT ADDITION*/ - /client/proc/change_title_screen_notice, /*SKYRAT EDIT ADDITION*/ - /client/proc/fix_say, /*SKYRAT EDIT ADDITION*/ - /client/proc/one_click_antag, /*ONE CLICK ANTAG - SKYRAT EDIT ADDITION*/ - /client/proc/request_more_opfor, /*SKYRAT EDIT ADDITION*/ - /client/proc/spawn_liquid, /*SKYRAT EDIT ADDITION*/ - /client/proc/spawn_mob_spawner, /*SKYRAT EDIT ADDITION*/ - /client/proc/spawn_pollution, /*SKYRAT EDIT ADDITION*/ - /client/proc/spawn_sunbeam, /*SKYRAT EDIT ADDITION*/ - /client/proc/intensity_credits_panel, /*SKYRAT EDIT ADDITION*/ - /client/proc/toggle_bsa, /*SKYRAT EDIT ADDITION*/ - /client/proc/try_stop_delam, /*SKYRAT EDIT ADDITION*/ - /client/proc/toggle_delam_suppression, /*SKYRAT EDIT ADDITION*/ - )) -GLOBAL_PROTECT(admin_verbs_fun) -GLOBAL_LIST_INIT(admin_verbs_spawn, list(/datum/admins/proc/spawn_atom, /datum/admins/proc/podspawn_atom, /datum/admins/proc/spawn_cargo, /datum/admins/proc/spawn_objasmob, /client/proc/respawn_character, /datum/admins/proc/beaker_panel)) -GLOBAL_PROTECT(admin_verbs_spawn) -GLOBAL_LIST_INIT(admin_verbs_server, world.AVerbsServer()) -GLOBAL_PROTECT(admin_verbs_server) -/world/proc/AVerbsServer() - return list( -// Admin datums - /datum/admins/proc/delay, - /datum/admins/proc/delay_round_end, - /datum/admins/proc/end_round, - /datum/admins/proc/restart, - /datum/admins/proc/startnow, - /datum/admins/proc/toggleaban, - /datum/admins/proc/toggleAI, -// Client procs - /client/proc/adminchangemap, - /client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/ - /client/proc/cmd_debug_del_all, - /client/proc/cmd_debug_force_del_all, - /client/proc/cmd_debug_hard_del_all, - /client/proc/everyone_random, - /client/proc/forcerandomrotate, - /client/proc/generate_job_config, - /client/proc/panicbunker, - /client/proc/toggle_cdn, - /client/proc/toggle_hub, - /client/proc/toggle_interviews, - /client/proc/toggle_random_events, - ) -GLOBAL_LIST_INIT(admin_verbs_debug, world.AVerbsDebug()) -GLOBAL_PROTECT(admin_verbs_debug) -/world/proc/AVerbsDebug() - return list( - #ifdef TESTING /* Keep these at the top to not make the list look fugly */ - /client/proc/check_missing_sprites, - #endif - /proc/machine_upgrade, - /datum/admins/proc/create_or_modify_area, - /client/proc/adventure_manager, - /client/proc/atmos_control, - /client/proc/callproc, - /client/proc/callproc_datum, - /client/proc/check_bomb_impacts, - /client/proc/check_timer_sources, - /client/proc/clear_dynamic_transit, - /client/proc/cmd_admin_debug_traitor_objectives, - /client/proc/cmd_admin_delete, - /client/proc/cmd_admin_list_open_jobs, - /client/proc/cmd_admin_toggle_fov, - /client/proc/cmd_debug_del_all, - /client/proc/cmd_debug_force_del_all, - /client/proc/cmd_debug_hard_del_all, - /client/proc/cmd_debug_make_powernets, - /client/proc/cmd_debug_mob_lists, - /client/proc/cmd_display_del_log, - /client/proc/cmd_display_init_log, - /client/proc/cmd_display_overlay_log, - /client/proc/Debug2, - /client/proc/debug_controller, - /client/proc/debug_hallucination_weighted_list_per_type, - /client/proc/debug_huds, - /client/proc/debugNatureMapGenerator, - /client/proc/debug_plane_masters, - /client/proc/debug_spell_requirements, - /client/proc/display_sendmaps, - /client/proc/enable_mapping_verbs, - /client/proc/generate_wikichem_list, - /client/proc/get_dynex_power, /*debug verbs for dynex explosions.*/ - /client/proc/get_dynex_range, /*debug verbs for dynex explosions.*/ - /client/proc/jump_to_ruin, - /client/proc/load_circuit, - /client/proc/map_export, - /client/proc/map_template_load, - /client/proc/map_template_upload, - /client/proc/modify_goals, - /client/proc/open_colorblind_test, - /client/proc/open_lua_editor, - /client/proc/outfit_manager, - /client/proc/populate_world, - /client/proc/pump_random_event, - /client/proc/print_cards, - /client/proc/reestablish_tts_connection, - /client/proc/reload_cards, - /client/proc/reload_configuration, - /client/proc/restart_controller, - /client/proc/run_empty_query, - /client/proc/SDQL2_query, - /client/proc/set_dynex_scale, - /client/proc/spawn_debug_full_crew, - /client/proc/test_cardpack_distribution, - /client/proc/test_movable_UI, - /client/proc/test_snap_UI, - /client/proc/toggle_cdn, - /client/proc/toggle_medal_disable, - /client/proc/unload_ctf, - /client/proc/validate_cards, - /client/proc/validate_puzzgrids, - /client/proc/GeneratePipeSpritesheet, - /client/proc/view_runtimes, - /client/proc/stop_weather, - /client/proc/reload_interactions, /*SKYRAT EDIT ADDITION*/ - /client/proc/test_area_spawner, /*AUTOMAPPER - SKYRAT EDIT ADDITION*/ - /client/proc/toggle_liquid_debug, /*SKYRAT EDIT ADDITION*/ - - /client/proc/debug_maintenance_loot //Bubberstation addition. - ) -GLOBAL_LIST_INIT(admin_verbs_possess, list(/proc/possess, GLOBAL_PROC_REF(release))) -GLOBAL_PROTECT(admin_verbs_possess) -/// SKYRAT EDIT BEGIN - Player Rank Manager - ORIGINAL: GLOBAL_LIST_INIT(admin_verbs_permissions, list(/client/proc/edit_admin_permissions)) -GLOBAL_LIST_INIT(admin_verbs_permissions, list( - /client/proc/edit_admin_permissions, - /client/proc/manage_player_ranks, - /client/proc/migrate_player_ranks, - )) -/// SKYRAT EDIT END -GLOBAL_PROTECT(admin_verbs_permissions) -GLOBAL_LIST_INIT(admin_verbs_poll, list(/client/proc/poll_panel)) -GLOBAL_PROTECT(admin_verbs_poll) - /client/proc/add_admin_verbs() - if(holder) - control_freak = CONTROL_FREAK_SKIN | CONTROL_FREAK_MACROS - - var/rights = holder.rank_flags() - add_verb(src, GLOB.admin_verbs_default) - if(rights & R_BUILD) - add_verb(src, /client/proc/togglebuildmodeself) - if(rights & R_ADMIN) - add_verb(src, GLOB.admin_verbs_admin) - if(rights & R_BAN) - add_verb(src, GLOB.admin_verbs_ban) - if(rights & R_FUN) - add_verb(src, GLOB.admin_verbs_fun) - if(rights & R_SERVER) - add_verb(src, GLOB.admin_verbs_server) - if(rights & R_DEBUG) - add_verb(src, GLOB.admin_verbs_debug) - if(rights & R_POSSESS) - add_verb(src, GLOB.admin_verbs_possess) - if(rights & R_PERMISSIONS) - add_verb(src, GLOB.admin_verbs_permissions) - if(rights & R_STEALTH) - add_verb(src, /client/proc/stealth) - if(rights & R_POLL) - add_verb(src, GLOB.admin_verbs_poll) - if(rights & R_SOUND) - add_verb(src, GLOB.admin_verbs_sounds) - if(CONFIG_GET(string/invoke_youtubedl)) - 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 + control_freak = CONTROL_FREAK_SKIN | CONTROL_FREAK_MACROS + SSadmin_verbs.assosciate_admin(src) /client/proc/remove_admin_verbs() - remove_verb(src, list( - GLOB.admin_verbs_default, - /client/proc/togglebuildmodeself, - GLOB.admin_verbs_admin, - GLOB.admin_verbs_ban, - GLOB.admin_verbs_fun, - GLOB.admin_verbs_server, - GLOB.admin_verbs_debug, - GLOB.admin_verbs_possess, - GLOB.admin_verbs_permissions, - /client/proc/stealth, - GLOB.admin_verbs_poll, - GLOB.admin_verbs_sounds, - /client/proc/play_web_sound, - GLOB.admin_verbs_spawn, - /*Debug verbs added by "show debug verbs"*/ - GLOB.admin_verbs_debug_mapping, - /client/proc/disable_mapping_verbs, - /client/proc/readmin - )) + control_freak = initial(control_freak) + SSadmin_verbs.deassosciate_admin(src) -/client/proc/hide_verbs() - set name = "Adminverbs - Hide All" - set category = "Admin" +ADMIN_VERB(hide_verbs, R_NONE, "Adminverbs - Hide All", "Hide most of your admin verbs.", ADMIN_CATEGORY_MAIN) + user.remove_admin_verbs() + add_verb(user, /client/proc/show_verbs) - remove_admin_verbs() - add_verb(src, /client/proc/show_verbs) - - to_chat(src, span_interface("Almost all of your adminverbs have been hidden."), confidential = TRUE) + to_chat(user, span_interface("Almost all of your adminverbs have been hidden."), confidential = TRUE) BLACKBOX_LOG_ADMIN_VERB("Hide All Adminverbs") - return -/client/proc/show_verbs() - set name = "Adminverbs - Show" - set category = "Admin" - - remove_verb(src, /client/proc/show_verbs) - add_admin_verbs() - - to_chat(src, span_interface("All of your adminverbs are now visible."), confidential = TRUE) - BLACKBOX_LOG_ADMIN_VERB("Show Adminverbs") - - - - -/client/proc/admin_ghost() - set category = "Admin.Game" - set name = "Aghost" - if(!holder) - return +ADMIN_VERB(admin_ghost, R_ADMIN, "AGhost", "Become a ghost without DNR.", ADMIN_CATEGORY_GAME) . = TRUE - if(isobserver(mob)) + if(isobserver(user.mob)) //re-enter - var/mob/dead/observer/ghost = mob + var/mob/dead/observer/ghost = user.mob if(!ghost.mind || !ghost.mind.current) //won't do anything if there is no body return FALSE if(!ghost.can_reenter_corpse) - log_admin("[key_name(usr)] re-entered corpse") - message_admins("[key_name_admin(usr)] re-entered corpse") + log_admin("[key_name(user)] re-entered corpse") + message_admins("[key_name_admin(user)] re-entered corpse") ghost.can_reenter_corpse = 1 //force re-entering even when otherwise not possible ghost.reenter_corpse() BLACKBOX_LOG_ADMIN_VERB("Admin Reenter") - else if(isnewplayer(mob)) - to_chat(src, "Error: Aghost: Can't admin-ghost whilst in the lobby. Join or Observe first.", confidential = TRUE) + else if(isnewplayer(user.mob)) + to_chat(user, "Error: Aghost: Can't admin-ghost whilst in the lobby. Join or Observe first.", confidential = TRUE) return FALSE else //ghostize - log_admin("[key_name(usr)] admin ghosted.") - message_admins("[key_name_admin(usr)] admin ghosted.") - var/mob/body = mob + log_admin("[key_name(user)] admin ghosted.") + message_admins("[key_name_admin(user)] admin ghosted.") + var/mob/body = user.mob body.ghostize(TRUE) - init_verbs() + user.init_verbs() if(body && !body.key) - body.key = "@[key]" //Haaaaaaaack. But the people have spoken. If it breaks; blame adminbus + body.key = "@[user.key]" //Haaaaaaaack. But the people have spoken. If it breaks; blame adminbus BLACKBOX_LOG_ADMIN_VERB("Admin Ghost") -/client/proc/invisimin() - set name = "Invisimin" - set category = "Admin.Game" - set desc = "Toggles ghost-like invisibility (Don't abuse this)" - - if(isnull(holder) || isnull(mob)) +ADMIN_VERB(invisimin, R_ADMIN, "Invisimin", "Toggles ghost-like invisibility.", ADMIN_CATEGORY_GAME) + if(HAS_TRAIT(user.mob, TRAIT_INVISIMIN)) + REMOVE_TRAIT(user.mob, TRAIT_INVISIMIN, ADMIN_TRAIT) + user.mob.add_to_all_human_data_huds() + user.mob.RemoveInvisibility(INVISIBILITY_SOURCE_INVISIMIN) + to_chat(user, span_adminnotice(span_bold("Invisimin off. Invisibility reset.")), confidential = TRUE) return - if(HAS_TRAIT(mob, TRAIT_INVISIMIN)) - REMOVE_TRAIT(mob, TRAIT_INVISIMIN, ADMIN_TRAIT) - mob.add_to_all_human_data_huds() - mob.RemoveInvisibility(INVISIBILITY_SOURCE_INVISIMIN) - to_chat(mob, span_adminnotice(span_bold("Invisimin off. Invisibility reset.")), confidential = TRUE) - return + ADD_TRAIT(user.mob, TRAIT_INVISIMIN, ADMIN_TRAIT) + user.mob.remove_from_all_data_huds() + user.mob.SetInvisibility(INVISIBILITY_OBSERVER, INVISIBILITY_SOURCE_INVISIMIN, INVISIBILITY_PRIORITY_ADMIN) + to_chat(user, span_adminnotice(span_bold("Invisimin on. You are now as invisible as a ghost.")), confidential = TRUE) - ADD_TRAIT(mob, TRAIT_INVISIMIN, ADMIN_TRAIT) - mob.remove_from_all_data_huds() - mob.SetInvisibility(INVISIBILITY_OBSERVER, INVISIBILITY_SOURCE_INVISIMIN, INVISIBILITY_PRIORITY_ADMIN) - to_chat(mob, span_adminnotice(span_bold("Invisimin on. You are now as invisible as a ghost.")), confidential = TRUE) - -/client/proc/check_antagonists() - set name = "Check Antagonists" - set category = "Admin.Game" - if(holder) - holder.check_antagonists() - log_admin("[key_name(usr)] checked antagonists.") //for tsar~ - if(!isobserver(usr) && SSticker.HasRoundStarted()) - message_admins("[key_name_admin(usr)] checked antagonists.") +ADMIN_VERB(check_antagonists, R_ADMIN, "Check Antagonists", "See all antagonists for the round.", ADMIN_CATEGORY_GAME) + user.holder.check_antagonists() + log_admin("[key_name(user)] checked antagonists.") + if(!isobserver(user.mob) && SSticker.HasRoundStarted()) + message_admins("[key_name_admin(user)] checked antagonists.") BLACKBOX_LOG_ADMIN_VERB("Check Antagonists") -/client/proc/list_bombers() - set name = "List Bombers" - set category = "Admin.Game" - if(!holder) - return - holder.list_bombers() +ADMIN_VERB(list_bombers, R_ADMIN, "List Bombers", "Look at all bombs and their likely culprit.", ADMIN_CATEGORY_GAME) + user.holder.list_bombers() BLACKBOX_LOG_ADMIN_VERB("List Bombers") -/client/proc/list_signalers() - set name = "List Signalers" - set category = "Admin.Game" - if(!holder) - return - holder.list_signalers() +ADMIN_VERB(list_signalers, R_ADMIN, "List Signalers", "View all signalers.", ADMIN_CATEGORY_GAME) + user.holder.list_signalers() BLACKBOX_LOG_ADMIN_VERB("List Signalers") -/client/proc/list_law_changes() - set name = "List Law Changes" - set category = "Debug" - if(!holder) - return - holder.list_law_changes() +ADMIN_VERB(list_law_changes, R_ADMIN, "List Law Changes", "View all AI law changes.", ADMIN_CATEGORY_DEBUG) + user.holder.list_law_changes() BLACKBOX_LOG_ADMIN_VERB("List Law Changes") -/client/proc/show_manifest() - set name = "Show Manifest" - set category = "Debug" - if(!holder) - return - holder.show_manifest() +ADMIN_VERB(show_manifest, R_ADMIN, "Show Manifest", "View the shift's Manifest.", ADMIN_CATEGORY_DEBUG) + user.holder.show_manifest() BLACKBOX_LOG_ADMIN_VERB("Show Manifest") -/client/proc/list_dna() - set name = "List DNA" - set category = "Debug" - if(!holder) - return - holder.list_dna() +ADMIN_VERB(list_dna, R_ADMIN, "List DNA", "View DNA.", ADMIN_CATEGORY_DEBUG) + user.holder.list_dna() BLACKBOX_LOG_ADMIN_VERB("List DNA") -/client/proc/list_fingerprints() - set name = "List Fingerprints" - set category = "Debug" - if(!holder) - return - holder.list_fingerprints() +ADMIN_VERB(list_fingerprints, R_ADMIN, "List Fingerprints", "View fingerprints.", ADMIN_CATEGORY_DEBUG) + user.holder.list_fingerprints() BLACKBOX_LOG_ADMIN_VERB("List Fingerprints") -/client/proc/ban_panel() - set name = "Banning Panel" - set category = "Admin" - if(!check_rights(R_BAN)) - return - holder.ban_panel() +ADMIN_VERB(ban_panel, R_BAN, "Banning Panel", "Ban players here.", ADMIN_CATEGORY_MAIN) + user.holder.ban_panel() BLACKBOX_LOG_ADMIN_VERB("Banning Panel") -/client/proc/unban_panel() - set name = "Unbanning Panel" - set category = "Admin" - if(!check_rights(R_BAN)) - return - holder.unban_panel() +ADMIN_VERB(unban_panel, R_BAN, "Unbanning Panel", "Unban players here.", ADMIN_CATEGORY_MAIN) + user.holder.unban_panel() BLACKBOX_LOG_ADMIN_VERB("Unbanning Panel") -/client/proc/game_panel() - set name = "Game Panel" - set category = "Admin.Game" - if(holder) - holder.Game() +ADMIN_VERB(game_panel, R_ADMIN, "Game Panel", "Look at the state of the game.", ADMIN_CATEGORY_GAME) + user.holder.Game() BLACKBOX_LOG_ADMIN_VERB("Game Panel") -/client/proc/poll_panel() - set name = "Server Poll Management" - set category = "Admin" - if(!check_rights(R_POLL)) - return - holder.poll_list_panel() +ADMIN_VERB(poll_panel, R_POLL, "Server Poll Management", "View and manage polls.", ADMIN_CATEGORY_MAIN) + user.holder.poll_list_panel() BLACKBOX_LOG_ADMIN_VERB("Server Poll Management") /// Returns this client's stealthed ckey @@ -535,16 +133,11 @@ GLOBAL_PROTECT(admin_verbs_poll) /client/proc/createStealthKey() GLOB.stealthminID["[ckey]"] = generateStealthCkey() -/client/proc/stealth() - set category = "Admin" - set name = "Stealth Mode" - if(!holder) - return - - if(holder.fakekey) - disable_stealth_mode() +ADMIN_VERB(stealth, R_STEALTH, "Stealth Mode", "Toggle stealth.", ADMIN_CATEGORY_MAIN) + if(user.holder.fakekey) + user.disable_stealth_mode() else - enable_stealth_mode() + user.enable_stealth_mode() BLACKBOX_LOG_ADMIN_VERB("Stealth Mode") @@ -589,117 +182,86 @@ GLOBAL_PROTECT(admin_verbs_poll) #undef STEALTH_MODE_TRAIT -/client/proc/drop_bomb() - set category = "Admin.Fun" - set name = "Drop Bomb" - set desc = "Cause an explosion of varying strength at your location." - +ADMIN_VERB(drop_bomb, R_FUN, "Drop Bomb", "Cause an explosion of varying strength at your location", ADMIN_CATEGORY_FUN) var/list/choices = list("Small Bomb (1, 2, 3, 3)", "Medium Bomb (2, 3, 4, 4)", "Big Bomb (3, 5, 7, 5)", "Maxcap", "Custom Bomb") - var/choice = tgui_input_list(src, "What size explosion would you like to produce? NOTE: You can do all this rapidly and in an IC manner (using cruise missiles!) with the Config/Launch Supplypod verb. WARNING: These ignore the maxcap", "Drop Bomb", choices) + var/choice = tgui_input_list(user, "What size explosion would you like to produce? NOTE: You can do all this rapidly and in an IC manner (using cruise missiles!) with the Config/Launch Supplypod verb. WARNING: These ignore the maxcap", "Drop Bomb", choices) if(isnull(choice)) return - var/turf/epicenter = mob.loc + var/turf/epicenter = user.mob.loc switch(choice) if("Small Bomb (1, 2, 3, 3)") - explosion(epicenter, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 3, flash_range = 3, adminlog = TRUE, ignorecap = TRUE, explosion_cause = mob) + explosion(epicenter, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 3, flash_range = 3, adminlog = TRUE, ignorecap = TRUE, explosion_cause = user.mob) if("Medium Bomb (2, 3, 4, 4)") - explosion(epicenter, devastation_range = 2, heavy_impact_range = 3, light_impact_range = 4, flash_range = 4, adminlog = TRUE, ignorecap = TRUE, explosion_cause = mob) + explosion(epicenter, devastation_range = 2, heavy_impact_range = 3, light_impact_range = 4, flash_range = 4, adminlog = TRUE, ignorecap = TRUE, explosion_cause = user.mob) if("Big Bomb (3, 5, 7, 5)") - explosion(epicenter, devastation_range = 3, heavy_impact_range = 5, light_impact_range = 7, flash_range = 5, adminlog = TRUE, ignorecap = TRUE, explosion_cause = mob) + explosion(epicenter, devastation_range = 3, heavy_impact_range = 5, light_impact_range = 7, flash_range = 5, adminlog = TRUE, ignorecap = TRUE, explosion_cause = user.mob) if("Maxcap") - explosion(epicenter, devastation_range = GLOB.MAX_EX_DEVESTATION_RANGE, heavy_impact_range = GLOB.MAX_EX_HEAVY_RANGE, light_impact_range = GLOB.MAX_EX_LIGHT_RANGE, flash_range = GLOB.MAX_EX_FLASH_RANGE, adminlog = TRUE, ignorecap = TRUE, explosion_cause = mob) + explosion(epicenter, devastation_range = GLOB.MAX_EX_DEVESTATION_RANGE, heavy_impact_range = GLOB.MAX_EX_HEAVY_RANGE, light_impact_range = GLOB.MAX_EX_LIGHT_RANGE, flash_range = GLOB.MAX_EX_FLASH_RANGE, adminlog = TRUE, ignorecap = TRUE, explosion_cause = user.mob) if("Custom Bomb") - var/range_devastation = input("Devastation range (in tiles):") as null|num + var/range_devastation = input(user, "Devastation range (in tiles):") as null|num if(range_devastation == null) return - var/range_heavy = input("Heavy impact range (in tiles):") as null|num + var/range_heavy = input(user, "Heavy impact range (in tiles):") as null|num if(range_heavy == null) return - var/range_light = input("Light impact range (in tiles):") as null|num + var/range_light = input(user, "Light impact range (in tiles):") as null|num if(range_light == null) return - var/range_flash = input("Flash range (in tiles):") as null|num + var/range_flash = input(user, "Flash range (in tiles):") as null|num if(range_flash == null) return if(range_devastation > GLOB.MAX_EX_DEVESTATION_RANGE || range_heavy > GLOB.MAX_EX_HEAVY_RANGE || range_light > GLOB.MAX_EX_LIGHT_RANGE || range_flash > GLOB.MAX_EX_FLASH_RANGE) - if(tgui_alert(usr, "Bomb is bigger than the maxcap. Continue?",,list("Yes","No")) != "Yes") + if(tgui_alert(user, "Bomb is bigger than the maxcap. Continue?",,list("Yes","No")) != "Yes") return - epicenter = mob.loc //We need to reupdate as they may have moved again - explosion(epicenter, devastation_range = range_devastation, heavy_impact_range = range_heavy, light_impact_range = range_light, flash_range = range_flash, adminlog = TRUE, ignorecap = TRUE, explosion_cause = mob) - message_admins("[ADMIN_LOOKUPFLW(usr)] creating an admin explosion at [epicenter.loc].") - log_admin("[key_name(usr)] created an admin explosion at [epicenter.loc].") + epicenter = get_turf(user.mob) //We need to reupdate as they may have moved again + explosion(epicenter, devastation_range = range_devastation, heavy_impact_range = range_heavy, light_impact_range = range_light, flash_range = range_flash, adminlog = TRUE, ignorecap = TRUE, explosion_cause = user.mob) + message_admins("[ADMIN_LOOKUPFLW(user.mob)] creating an admin explosion at [epicenter.loc].") + log_admin("[key_name(user)] created an admin explosion at [epicenter.loc].") BLACKBOX_LOG_ADMIN_VERB("Drop Bomb") -/client/proc/drop_dynex_bomb() - set category = "Admin.Fun" - set name = "Drop DynEx Bomb" - set desc = "Cause an explosion of varying strength at your location." +ADMIN_VERB(drop_bomb_dynex, R_FUN, "Drop DynEx Bomb", "Cause an explosion of varying strength at your location.", ADMIN_CATEGORY_FUN) + var/ex_power = input(user, "Explosive Power:") as null|num + var/turf/epicenter = get_turf(user.mob) + if(!ex_power || !epicenter) + return + dyn_explosion(epicenter, ex_power) + message_admins("[ADMIN_LOOKUPFLW(user.mob)] creating an admin explosion at [epicenter.loc].") + log_admin("[key_name(user)] created an admin explosion at [epicenter.loc].") + BLACKBOX_LOG_ADMIN_VERB("Drop Dynamic Bomb") - var/ex_power = input("Explosive Power:") as null|num - var/turf/epicenter = mob.loc - if(ex_power && epicenter) - dyn_explosion(epicenter, ex_power) - message_admins("[ADMIN_LOOKUPFLW(usr)] creating an admin explosion at [epicenter.loc].") - log_admin("[key_name(usr)] created an admin explosion at [epicenter.loc].") - BLACKBOX_LOG_ADMIN_VERB("Drop Dynamic Bomb") - -/client/proc/get_dynex_range() - set category = "Debug" - set name = "Get DynEx Range" - set desc = "Get the estimated range of a bomb, using explosive power." - - var/ex_power = input("Explosive Power:") as null|num +ADMIN_VERB(get_dynex_range, R_FUN, "Get DynEx Range", "Get the estimated range of a bomb using explosive power.", ADMIN_CATEGORY_DEBUG) + var/ex_power = input(user, "Explosive Power:") as null|num if (isnull(ex_power)) return var/range = round((2 * ex_power)**GLOB.DYN_EX_SCALE) - to_chat(usr, "Estimated Explosive Range: (Devastation: [round(range*0.25)], Heavy: [round(range*0.5)], Light: [round(range)])", confidential = TRUE) + to_chat(user, "Estimated Explosive Range: (Devastation: [round(range*0.25)], Heavy: [round(range*0.5)], Light: [round(range)])", confidential = TRUE) -/client/proc/get_dynex_power() - set category = "Debug" - set name = "Get DynEx Power" - set desc = "Get the estimated required power of a bomb, to reach a specific range." - - var/ex_range = input("Light Explosion Range:") as null|num +ADMIN_VERB(get_dynex_power, R_FUN, "Get DynEx Power", "Get the estimated required power of a bomb to reach the given range.", ADMIN_CATEGORY_DEBUG) + var/ex_range = input(user, "Light Explosion Range:") as null|num if (isnull(ex_range)) return var/power = (0.5 * ex_range)**(1/GLOB.DYN_EX_SCALE) - to_chat(usr, "Estimated Explosive Power: [power]", confidential = TRUE) + to_chat(user, "Estimated Explosive Power: [power]", confidential = TRUE) -/client/proc/set_dynex_scale() - set category = "Debug" - set name = "Set DynEx Scale" - set desc = "Set the scale multiplier of dynex explosions. The default is 0.5." - - var/ex_scale = input("New DynEx Scale:") as null|num +ADMIN_VERB(set_dynex_scale, R_FUN, "Set DynEx Scale", "Set the scale multiplier on dynex explosions. Default 0.5.", ADMIN_CATEGORY_DEBUG) + var/ex_scale = input(user, "New DynEx Scale:") as null|num if(!ex_scale) return GLOB.DYN_EX_SCALE = ex_scale - log_admin("[key_name(usr)] has modified Dynamic Explosion Scale: [ex_scale]") - message_admins("[key_name_admin(usr)] has modified Dynamic Explosion Scale: [ex_scale]") + log_admin("[key_name(user)] has modified Dynamic Explosion Scale: [ex_scale]") + message_admins("[key_name_admin(user)] has modified Dynamic Explosion Scale: [ex_scale]") -/client/proc/atmos_control() - set name = "Atmos Control Panel" - set category = "Debug" - if(!check_rights(R_DEBUG)) - return - SSair.ui_interact(mob) +ADMIN_VERB(atmos_control, R_DEBUG|R_SERVER, "Atmos Control Panel", "Open the atmospherics control panel.", ADMIN_CATEGORY_DEBUG) + SSair.ui_interact(user.mob) -/client/proc/reload_cards() - set name = "Reload Cards" - set category = "Debug" - if(!check_rights(R_DEBUG)) - return +ADMIN_VERB(reload_cards, R_DEBUG, "Reload Cards", "Reload all TCG cards.", ADMIN_CATEGORY_DEBUG) if(!SStrading_card_game.loaded) message_admins("The card subsystem is not currently loaded") return SStrading_card_game.reloadAllCardFiles() -/client/proc/validate_cards() - set name = "Validate Cards" - set category = "Debug" - if(!check_rights(R_DEBUG)) - return +ADMIN_VERB(validate_cards, R_DEBUG, "Validate Cards", "Validate the card settings.", ADMIN_CATEGORY_DEBUG) if(!SStrading_card_game.loaded) message_admins("The card subsystem is not currently loaded") return @@ -710,66 +272,55 @@ GLOBAL_PROTECT(admin_verbs_poll) else message_admins("No errors found in card rarities or overrides.") -/client/proc/test_cardpack_distribution() - set name = "Test Cardpack Distribution" - set category = "Debug" - if(!check_rights(R_DEBUG)) - return +ADMIN_VERB(test_cardpack_distribution, R_DEBUG, "Test Cardpack Distribution", "Test the distribution of a card pack.", ADMIN_CATEGORY_DEBUG) if(!SStrading_card_game.loaded) message_admins("The card subsystem is not currently loaded") return - var/pack = tgui_input_list(usr, "Which pack should we test?", "You fucked it didn't you", sort_list(SStrading_card_game.card_packs)) + var/pack = tgui_input_list(user, "Which pack should we test?", "You fucked it didn't you", sort_list(SStrading_card_game.card_packs)) if(!pack) return - var/batch_count = tgui_input_number(usr, "How many times should we open it?", "Don't worry, I understand") - var/batch_size = tgui_input_number(usr, "How many cards per batch?", "I hope you remember to check the validation") - var/guar = tgui_input_number(usr, "Should we use the pack's guaranteed rarity? If so, how many?", "We've all been there. Man you should have seen the old system") - + var/batch_count = tgui_input_number(user, "How many times should we open it?", "Don't worry, I understand") + var/batch_size = tgui_input_number(user, "How many cards per batch?", "I hope you remember to check the validation") + var/guar = tgui_input_number(user, "Should we use the pack's guaranteed rarity? If so, how many?", "We've all been there. Man you should have seen the old system") SStrading_card_game.check_card_distribution(pack, batch_size, batch_count, guar) -/client/proc/print_cards() - set name = "Print Cards" - set category = "Debug" +ADMIN_VERB(print_cards, R_DEBUG, "Print Cards", "Print all cards to chat.", ADMIN_CATEGORY_DEBUG) SStrading_card_game.printAllCards() -/client/proc/give_mob_action(mob/ability_recipient in GLOB.mob_list) - set category = "Admin.Fun" - set name = "Give Mob Action" - set desc = "Gives a mob ability to a mob." - +ADMIN_VERB(give_mob_action, R_FUN, "Give Mob Action", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/ability_recipient) var/static/list/all_mob_actions = sort_list(subtypesof(/datum/action/cooldown/mob_cooldown), GLOBAL_PROC_REF(cmp_typepaths_asc)) var/static/list/actions_by_name = list() if (!length(actions_by_name)) for (var/datum/action/cooldown/mob_cooldown as anything in all_mob_actions) actions_by_name["[initial(mob_cooldown.name)] ([mob_cooldown])"] = mob_cooldown - var/ability = tgui_input_list(usr, "Choose an ability", "Ability", actions_by_name) + var/ability = tgui_input_list(user, "Choose an ability", "Ability", actions_by_name) if(isnull(ability)) return var/ability_type = actions_by_name[ability] var/datum/action/cooldown/mob_cooldown/add_ability - var/make_sequence = tgui_alert(usr, "Would you like this action to be a sequence of multiple abilities?", "Sequence Ability", list("Yes", "No")) + var/make_sequence = tgui_alert(user, "Would you like this action to be a sequence of multiple abilities?", "Sequence Ability", list("Yes", "No")) if(make_sequence == "Yes") add_ability = new /datum/action/cooldown/mob_cooldown(ability_recipient) add_ability.sequence_actions = list() while(!isnull(ability_type)) - var/ability_delay = tgui_input_number(usr, "Enter the delay in seconds before the next ability in the sequence is used", "Ability Delay", 2) + var/ability_delay = tgui_input_number(user, "Enter the delay in seconds before the next ability in the sequence is used", "Ability Delay", 2) if(isnull(ability_delay) || ability_delay < 0) ability_delay = 0 add_ability.sequence_actions[ability_type] = ability_delay * 1 SECONDS - ability = tgui_input_list(usr, "Choose a new sequence ability", "Sequence Ability", actions_by_name) + ability = tgui_input_list(user, "Choose a new sequence ability", "Sequence Ability", actions_by_name) ability_type = actions_by_name[ability] - var/ability_cooldown = tgui_input_number(usr, "Enter the sequence abilities cooldown in seconds", "Ability Cooldown", 2) + var/ability_cooldown = tgui_input_number(user, "Enter the sequence abilities cooldown in seconds", "Ability Cooldown", 2) if(isnull(ability_cooldown) || ability_cooldown < 0) ability_cooldown = 2 add_ability.cooldown_time = ability_cooldown * 1 SECONDS - var/ability_melee_cooldown = tgui_input_number(usr, "Enter the abilities melee cooldown in seconds", "Melee Cooldown", 2) + var/ability_melee_cooldown = tgui_input_number(user, "Enter the abilities melee cooldown in seconds", "Melee Cooldown", 2) if(isnull(ability_melee_cooldown) || ability_melee_cooldown < 0) ability_melee_cooldown = 2 add_ability.melee_cooldown_time = ability_melee_cooldown * 1 SECONDS - add_ability.name = tgui_input_text(usr, "Choose ability name", "Ability name", "Generic Ability") + add_ability.name = tgui_input_text(user, "Choose ability name", "Ability name", "Generic Ability") add_ability.create_sequence_actions() else add_ability = new ability_type(ability_recipient) @@ -778,15 +329,11 @@ GLOBAL_PROTECT(admin_verbs_poll) return add_ability.Grant(ability_recipient) - message_admins("[key_name_admin(usr)] added mob ability [ability_type] to mob [ability_recipient].") - log_admin("[key_name(usr)] added mob ability [ability_type] to mob [ability_recipient].") + message_admins("[key_name_admin(user)] added mob ability [ability_type] to mob [ability_recipient].") + log_admin("[key_name(user)] added mob ability [ability_type] to mob [ability_recipient].") BLACKBOX_LOG_ADMIN_VERB("Add Mob Ability") -/client/proc/remove_mob_action(mob/removal_target in GLOB.mob_list) - set category = "Admin.Fun" - set name = "Remove Mob Action" - set desc = "Remove a special ability from the selected mob." - +ADMIN_VERB(remove_mob_action, R_FUN, "Remove Mob Action", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/removal_target) var/list/target_abilities = list() for(var/datum/action/cooldown/mob_cooldown/ability in removal_target.actions) target_abilities[ability.name] = ability @@ -794,7 +341,7 @@ GLOBAL_PROTECT(admin_verbs_poll) if(!length(target_abilities)) return - var/chosen_ability = tgui_input_list(usr, "Choose the spell to remove from [removal_target]", "Depower", sort_list(target_abilities)) + var/chosen_ability = tgui_input_list(user, "Choose the spell to remove from [removal_target]", "Depower", sort_list(target_abilities)) if(isnull(chosen_ability)) return var/datum/action/cooldown/mob_cooldown/to_remove = target_abilities[chosen_ability] @@ -802,20 +349,16 @@ GLOBAL_PROTECT(admin_verbs_poll) return qdel(to_remove) - log_admin("[key_name(usr)] removed the ability [chosen_ability] from [key_name(removal_target)].") - message_admins("[key_name_admin(usr)] removed the ability [chosen_ability] from [key_name_admin(removal_target)].") + log_admin("[key_name(user)] removed the ability [chosen_ability] from [key_name(removal_target)].") + message_admins("[key_name_admin(user)] removed the ability [chosen_ability] from [key_name_admin(removal_target)].") BLACKBOX_LOG_ADMIN_VERB("Remove Mob Ability") -/client/proc/give_spell(mob/spell_recipient in GLOB.mob_list) - set category = "Admin.Fun" - set name = "Give Spell" - set desc = "Gives a spell to a mob." - - var/which = tgui_alert(usr, "Chose by name or by type path?", "Chose option", list("Name", "Typepath")) +ADMIN_VERB(give_spell, R_FUN, "Give Spell", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/spell_recipient) + var/which = tgui_alert(user, "Chose by name or by type path?", "Chose option", list("Name", "Typepath")) if(!which) return if(QDELETED(spell_recipient)) - to_chat(usr, span_warning("The intended spell recipient no longer exists.")) + to_chat(user, span_warning("The intended spell recipient no longer exists.")) return var/list/spell_list = list() @@ -829,22 +372,22 @@ GLOBAL_PROTECT(admin_verbs_poll) else spell_list += to_add - var/chosen_spell = tgui_input_list(usr, "Choose the spell to give to [spell_recipient]", "ABRAKADABRA", sort_list(spell_list)) + var/chosen_spell = tgui_input_list(user, "Choose the spell to give to [spell_recipient]", "ABRAKADABRA", sort_list(spell_list)) if(isnull(chosen_spell)) return var/datum/action/cooldown/spell/spell_path = which == "Typepath" ? chosen_spell : spell_list[chosen_spell] if(!ispath(spell_path)) return - var/robeless = (tgui_alert(usr, "Would you like to force this spell to be robeless?", "Robeless Casting?", list("Force Robeless", "Use Spell Setting")) == "Force Robeless") + var/robeless = (tgui_alert(user, "Would you like to force this spell to be robeless?", "Robeless Casting?", list("Force Robeless", "Use Spell Setting")) == "Force Robeless") if(QDELETED(spell_recipient)) - to_chat(usr, span_warning("The intended spell recipient no longer exists.")) + to_chat(user, span_warning("The intended spell recipient no longer exists.")) return BLACKBOX_LOG_ADMIN_VERB("Give Spell") - log_admin("[key_name(usr)] gave [key_name(spell_recipient)] the spell [chosen_spell][robeless ? " (Forced robeless)" : ""].") - message_admins("[key_name_admin(usr)] gave [key_name_admin(spell_recipient)] the spell [chosen_spell][robeless ? " (Forced robeless)" : ""].") + log_admin("[key_name(user)] gave [key_name(spell_recipient)] the spell [chosen_spell][robeless ? " (Forced robeless)" : ""].") + message_admins("[key_name_admin(user)] gave [key_name_admin(spell_recipient)] the spell [chosen_spell][robeless ? " (Forced robeless)" : ""].") var/datum/action/cooldown/spell/new_spell = new spell_path(spell_recipient.mind || spell_recipient) @@ -854,14 +397,10 @@ GLOBAL_PROTECT(admin_verbs_poll) new_spell.Grant(spell_recipient) if(!spell_recipient.mind) - to_chat(usr, span_userdanger("Spells given to mindless mobs will belong to the mob and not their mind, \ + to_chat(user, span_userdanger("Spells given to mindless mobs will belong to the mob and not their mind, \ and as such will not be transferred if their mind changes body (Such as from Mindswap).")) -/client/proc/remove_spell(mob/removal_target in GLOB.mob_list) - set category = "Admin.Fun" - set name = "Remove Spell" - set desc = "Remove a spell from the selected mob." - +ADMIN_VERB(remove_spell, R_FUN, "Remove Spell", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/removal_target) var/list/target_spell_list = list() for(var/datum/action/cooldown/spell/spell in removal_target.actions) target_spell_list[spell.name] = spell @@ -869,7 +408,7 @@ GLOBAL_PROTECT(admin_verbs_poll) if(!length(target_spell_list)) return - var/chosen_spell = tgui_input_list(usr, "Choose the spell to remove from [removal_target]", "ABRAKADABRA", sort_list(target_spell_list)) + var/chosen_spell = tgui_input_list(user, "Choose the spell to remove from [removal_target]", "ABRAKADABRA", sort_list(target_spell_list)) if(isnull(chosen_spell)) return var/datum/action/cooldown/spell/to_remove = target_spell_list[chosen_spell] @@ -877,58 +416,39 @@ GLOBAL_PROTECT(admin_verbs_poll) return qdel(to_remove) - log_admin("[key_name(usr)] removed the spell [chosen_spell] from [key_name(removal_target)].") - message_admins("[key_name_admin(usr)] removed the spell [chosen_spell] from [key_name_admin(removal_target)].") + log_admin("[key_name(user)] removed the spell [chosen_spell] from [key_name(removal_target)].") + message_admins("[key_name_admin(user)] removed the spell [chosen_spell] from [key_name_admin(removal_target)].") BLACKBOX_LOG_ADMIN_VERB("Remove Spell") -/client/proc/give_disease(mob/living/T in GLOB.mob_living_list) - set category = "Admin.Fun" - set name = "Give Disease" - set desc = "Gives a Disease to a mob." - if(!istype(T)) - to_chat(src, span_notice("You can only give a disease to a mob of type /mob/living."), confidential = TRUE) - return - var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in sort_list(SSdisease.diseases, GLOBAL_PROC_REF(cmp_typepaths_asc)) +ADMIN_VERB(give_disease, R_FUN, "Give Disease", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/living/victim) + var/datum/disease/D = input(user, "Choose the disease to give to that guy", "ACHOO") as null|anything in sort_list(SSdisease.diseases, GLOBAL_PROC_REF(cmp_typepaths_asc)) if(!D) return - T.ForceContractDisease(new D, FALSE, TRUE) + victim.ForceContractDisease(new D, FALSE, TRUE) BLACKBOX_LOG_ADMIN_VERB("Give Disease") - log_admin("[key_name(usr)] gave [key_name(T)] the disease [D].") - message_admins(span_adminnotice("[key_name_admin(usr)] gave [key_name_admin(T)] the disease [D].")) + log_admin("[key_name(user)] gave [key_name(victim)] the disease [D].") + message_admins(span_adminnotice("[key_name_admin(user)] gave [key_name_admin(victim)] the disease [D].")) -/client/proc/object_say(obj/O in world) - set category = "Admin.Events" - set name = "OSay" - set desc = "Makes an object say something." - var/message = tgui_input_text(usr, "What do you want the message to be?", "Make Sound", encode = FALSE) +ADMIN_VERB_AND_CONTEXT_MENU(object_say, R_FUN, "OSay", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, obj/speaker in world) + var/message = tgui_input_text(user, "What do you want the message to be?", "Make Sound", encode = FALSE) if(!message) return - O.say(message, sanitize = FALSE) - log_admin("[key_name(usr)] made [O] at [AREACOORD(O)] say \"[message]\"") - message_admins(span_adminnotice("[key_name_admin(usr)] made [O] at [AREACOORD(O)]. say \"[message]\"")) + speaker.say(message, sanitize = FALSE) + log_admin("[key_name(user)] made [speaker] at [AREACOORD(speaker)] say \"[message]\"") + message_admins(span_adminnotice("[key_name_admin(user)] made [speaker] at [AREACOORD(speaker)]. say \"[message]\"")) BLACKBOX_LOG_ADMIN_VERB("Object Say") -/client/proc/togglebuildmodeself() - set name = "Toggle Build Mode Self" - set category = "Admin.Events" - if (!(holder.rank_flags() & R_BUILD)) - return - if(src.mob) - togglebuildmode(src.mob) + +ADMIN_VERB(build_mode_self, R_BUILD, "Toggle Build Mode Self", "Toggle build mode for yourself.", ADMIN_CATEGORY_EVENTS) + togglebuildmode(user.mob) // why is this a global proc??? BLACKBOX_LOG_ADMIN_VERB("Toggle Build Mode") -/client/proc/check_ai_laws() - set name = "Check AI Laws" - set category = "Admin.Game" - if(holder) - src.holder.output_ai_laws() - -/client/proc/manage_sect() - set name = "Manage Religious Sect" - set category = "Admin.Game" +ADMIN_VERB(check_ai_laws, R_ADMIN, "Check AI Laws", "View the current AI laws.", ADMIN_CATEGORY_GAME) + user.holder.output_ai_laws() +ADMIN_VERB(manage_sect, R_ADMIN, "Manage Religious Sect", "Manages the chaplain's religion.", ADMIN_CATEGORY_GAME) if (!isnull(GLOB.religious_sect)) var/you_sure = tgui_alert( - usr, + user, "The Chaplain has already chosen [GLOB.religious_sect.name], override their selection?", "Replace God?", list("Yes", "Cancel"), @@ -941,7 +461,7 @@ GLOBAL_PROTECT(admin_verbs_poll) choices["nothing"] = null for(var/datum/religion_sect/sect as anything in subtypesof(/datum/religion_sect)) choices[initial(sect.name)] = sect - var/choice = tgui_input_list(usr, "Set new Chaplain sect", "God Picker", choices) + var/choice = tgui_input_list(user, "Set new Chaplain sect", "God Picker", choices) if(isnull(choice)) return if(choice == "nothing") @@ -949,122 +469,51 @@ GLOBAL_PROTECT(admin_verbs_poll) return set_new_religious_sect(choices[choice], reset_existing = TRUE) -/client/proc/deadmin() - set name = "Deadmin" - set category = "Admin" - set desc = "Shed your admin powers." - - if(!holder) - return - - holder.deactivate() - - to_chat(src, span_interface("You are now a normal player.")) - log_admin("[src] deadminned themselves.") - message_admins("[src] deadminned themselves.") +ADMIN_VERB(deadmin, R_NONE, "DeAdmin", "Shed your admin powers.", ADMIN_CATEGORY_MAIN) + user.holder.deactivate() + to_chat(user, span_interface("You are now a normal player.")) + log_admin("[key_name(user)] deadminned themselves.") + message_admins("[key_name_admin(user)] deadminned themselves.") BLACKBOX_LOG_ADMIN_VERB("Deadmin") -/client/proc/readmin() - set name = "Readmin" - set category = "Admin" - set desc = "Regain your admin powers." - - var/datum/admins/A = GLOB.deadmins[ckey] - - if(!A) - A = GLOB.admin_datums[ckey] - if (!A) - var/msg = " is trying to readmin but they have no deadmin entry" - message_admins("[key_name_admin(src)][msg]") - log_admin_private("[key_name(src)][msg]") - return - - A.associate(src) - - if (!holder) - return //This can happen if an admin attempts to vv themself into somebody elses's deadmin datum by getting ref via brute force - - to_chat(src, span_interface("You are now an admin."), confidential = TRUE) - message_admins("[src] re-adminned themselves.") - log_admin("[src] re-adminned themselves.") - BLACKBOX_LOG_ADMIN_VERB("Readmin") - -/client/proc/populate_world(amount = 50) - set name = "Populate World" - set category = "Debug" - set desc = "(\"Amount of mobs to create\") Populate the world with test mobs." - +ADMIN_VERB(populate_world, R_DEBUG, "Populate World", "Populate the world with test mobs.", ADMIN_CATEGORY_DEBUG, amount = 50 as num) for (var/i in 1 to amount) var/turf/tile = get_safe_random_station_turf() var/mob/living/carbon/human/hooman = new(tile) hooman.equipOutfit(pick(subtypesof(/datum/outfit))) testing("Spawned test mob at [get_area_name(tile, TRUE)] ([tile.x],[tile.y],[tile.z])") -/client/proc/toggle_AI_interact() - set name = "Toggle Admin AI Interact" - set category = "Admin.Game" - set desc = "Allows you to interact with most machines as an AI would as a ghost" +ADMIN_VERB(toggle_ai_interact, R_ADMIN, "Toggle Admin AI Interact", "Allows you to interact with most machines as an AI would as a ghost.", ADMIN_CATEGORY_GAME) + user.AI_Interact = !user.AI_Interact + if(user.mob && isAdminGhostAI(user.mob)) + user.mob.has_unlimited_silicon_privilege = user.AI_Interact - AI_Interact = !AI_Interact - if(mob && isAdminGhostAI(mob)) - mob.has_unlimited_silicon_privilege = AI_Interact + log_admin("[key_name(user)] has [user.AI_Interact ? "activated" : "deactivated"] Admin AI Interact") + message_admins("[key_name_admin(user)] has [user.AI_Interact ? "activated" : "deactivated"] their AI interaction") - log_admin("[key_name(usr)] has [AI_Interact ? "activated" : "deactivated"] Admin AI Interact") - message_admins("[key_name_admin(usr)] has [AI_Interact ? "activated" : "deactivated"] their AI interaction") +ADMIN_VERB(debug_statpanel, R_DEBUG, "Debug Stat Panel", "Toggles local debug of the stat panel", ADMIN_CATEGORY_DEBUG) + user.stat_panel.send_message("create_debug") -/client/proc/debugstatpanel() - set name = "Debug Stat Panel" - set category = "Debug" - - src.stat_panel.send_message("create_debug") - -/client/proc/admin_2fa_verify() - set name = "Verify Admin" - set category = "Admin" - - var/datum/admins/admin = GLOB.admin_datums[ckey] - admin?.associate(src) - -/client/proc/display_sendmaps() - set name = "Send Maps Profile" - set category = "Debug" - - src << link("?debug=profile&type=sendmaps&window=test") - -/** - * Debug verb that spawns human crewmembers - * of each job type, gives them a mind and assigns the role, - * and injects them into the manifest, as if they were a "player". - * - * This spawns humans with minds and jobs, but does NOT make them 'players'. - * They're all clientles mobs with minds / jobs. - */ -/client/proc/spawn_debug_full_crew() - set name = "Spawn Debug Full Crew" - set desc = "Creates a full crew for the station, filling the datacore and assigning them all minds / jobs. Don't do this on live" - set category = "Debug" - - if(!check_rights(R_DEBUG)) - return - - var/mob/admin = usr +ADMIN_VERB(display_sendmaps, R_DEBUG, "Send Maps Profile", "View the profile.", ADMIN_CATEGORY_DEBUG) + user << link("?debug=profile&type=sendmaps&window=test") +ADMIN_VERB(spawn_debug_full_crew, R_DEBUG, "Spawn Debug Full Crew", "Creates a full crew for the station, flling datacore and assigning minds and jobs.", ADMIN_CATEGORY_DEBUG) if(SSticker.current_state != GAME_STATE_PLAYING) - to_chat(admin, "You should only be using this after a round has setup and started.") + to_chat(user, "You should only be using this after a round has setup and started.") return // Two input checks here to make sure people are certain when they're using this. - if(tgui_alert(admin, "This command will create a bunch of dummy crewmembers with minds, job, and datacore entries, which will take a while and fill the manifest.", "Spawn Crew", list("Yes", "Cancel")) != "Yes") + if(tgui_alert(user, "This command will create a bunch of dummy crewmembers with minds, job, and datacore entries, which will take a while and fill the manifest.", "Spawn Crew", list("Yes", "Cancel")) != "Yes") return - if(tgui_alert(admin, "I sure hope you aren't doing this on live. Are you sure?", "Spawn Crew (Be certain)", list("Yes", "Cancel")) != "Yes") + if(tgui_alert(user, "I sure hope you aren't doing this on live. Are you sure?", "Spawn Crew (Be certain)", list("Yes", "Cancel")) != "Yes") return // Find the observer spawn, so we have a place to dump the dummies. var/obj/effect/landmark/observer_start/observer_point = locate(/obj/effect/landmark/observer_start) in GLOB.landmarks_list var/turf/destination = get_turf(observer_point) if(!destination) - to_chat(admin, "Failed to find the observer spawn to send the dummies.") + to_chat(user, "Failed to find the observer spawn to send the dummies.") return // Okay, now go through all nameable occupations. @@ -1086,7 +535,7 @@ GLOBAL_PROTECT(admin_verbs_poll) // Assign the rank to the new player dummy. if(!SSjob.AssignRole(new_guy, job, do_eligibility_checks = FALSE)) qdel(new_guy) - to_chat(admin, "[rank] wasn't able to be spawned.") + to_chat(user, "[rank] wasn't able to be spawned.") continue // It's got a job, spawn in a human and shove it in the human. @@ -1107,13 +556,9 @@ GLOBAL_PROTECT(admin_verbs_poll) number_made++ CHECK_TICK - to_chat(admin, "[number_made] crewmembers have been created.") - -/// Debug verb for seeing at a glance what all spells have as set requirements -/client/proc/debug_spell_requirements() - set name = "Show Spell Requirements" - set category = "Debug" + to_chat(user, "[number_made] crewmembers have been created.") +ADMIN_VERB(debug_spell_requirements, R_DEBUG, "Debug Spell Requirements", "View all spells and their requirements.", ADMIN_CATEGORY_DEBUG) var/header = "Name Requirements" var/all_requirements = list() for(var/datum/action/cooldown/spell/spell as anything in typesof(/datum/action/cooldown/spell)) @@ -1141,69 +586,52 @@ GLOBAL_PROTECT(admin_verbs_poll) var/page_style = "" var/page_contents = "[page_style][header][jointext(all_requirements, "")]
" - var/datum/browser/popup = new(mob, "spellreqs", "Spell Requirements", 600, 400) + var/datum/browser/popup = new(user.mob, "spellreqs", "Spell Requirements", 600, 400) popup.set_content(page_contents) popup.open() -/client/proc/force_load_lazy_template() - set name = "Load/Jump Lazy Template" - set category = "Admin.Events" - if(!check_rights(R_ADMIN)) - return - +ADMIN_VERB(load_lazy_template, R_ADMIN, "Load/Jump Lazy Template", "Loads a lazy template and/or jumps to it.", ADMIN_CATEGORY_EVENTS) var/list/choices = LAZY_TEMPLATE_KEY_LIST_ALL() - var/choice = tgui_input_list(usr, "Key?", "Lazy Loader", choices) + var/choice = tgui_input_list(user, "Key?", "Lazy Loader", choices) if(!choice) return choice = choices[choice] if(!choice) - to_chat(usr, span_warning("No template with that key found, report this!")) + to_chat(user, span_warning("No template with that key found, report this!")) return var/already_loaded = LAZYACCESS(SSmapping.loaded_lazy_templates, choice) var/force_load = FALSE - if(already_loaded && (tgui_alert(usr, "Template already loaded.", "", list("Jump", "Load Again")) == "Load Again")) + if(already_loaded && (tgui_alert(user, "Template already loaded.", "", list("Jump", "Load Again")) == "Load Again")) force_load = TRUE var/datum/turf_reservation/reservation = SSmapping.lazy_load_template(choice, force = force_load) if(!reservation) - to_chat(usr, span_boldwarning("Failed to load template!")) + to_chat(user, span_boldwarning("Failed to load template!")) return - if(!isobserver(usr)) - admin_ghost() - usr.forceMove(reservation.bottom_left_turfs[1]) + if(!isobserver(user.mob)) + SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/admin_ghost) + user.mob.forceMove(reservation.bottom_left_turfs[1]) - message_admins("[key_name_admin(usr)] has loaded lazy template '[choice]'") - to_chat(usr, span_boldnicegreen("Template loaded, you have been moved to the bottom left of the reservation.")) + message_admins("[key_name_admin(user)] has loaded lazy template '[choice]'") + to_chat(user, span_boldnicegreen("Template loaded, you have been moved to the bottom left of the reservation.")) -/client/proc/library_control() - set name = "Library Management" - set category = "Admin" - if(!check_rights(R_BAN)) - return - - if(!holder.library_manager) - holder.library_manager = new() - holder.library_manager.ui_interact(usr) +ADMIN_VERB(library_control, R_BAN, "Library Management", "List and manage the Library.", ADMIN_CATEGORY_MAIN) + if(!user.holder.library_manager) + user.holder.library_manager = new + user.holder.library_manager.ui_interact(user.mob) BLACKBOX_LOG_ADMIN_VERB("Library Management") -/client/proc/create_mob_worm() - set category = "Admin.Fun" - set name = "Create Mob Worm" - set desc = "Attached a linked list of mobs to a marked mob" - if (!check_rights(R_FUN)) +ADMIN_VERB(create_mob_worm, R_FUN, "Create Mob Worm", "Attach a linked list of mobs to your marked mob.", ADMIN_CATEGORY_FUN) + if(!isliving(user.holder.marked_datum)) + to_chat(user, span_warning("Error: Please mark a mob to attach mobs to.")) return - if(isnull(holder)) - return - if(!isliving(holder.marked_datum)) - to_chat(usr, span_warning("Error: Please mark a mob to attach mobs to.")) - return - var/mob/living/head = holder.marked_datum + var/mob/living/head = user.holder.marked_datum var/attempted_target_path = tgui_input_text( - usr, + user, "Enter typepath of a mob you'd like to make your chain from.", "Typepath", "[/mob/living/basic/pet/dog/corgi/ian]", @@ -1218,7 +646,7 @@ GLOBAL_PROTECT(admin_verbs_poll) if(isnull(desired_mob) || !ispath(desired_mob) || QDELETED(head)) return //The user pressed "Cancel" - var/amount = tgui_input_number(usr, "How long should our tail be?", "Worm Configurator", default = 3, min_value = 1) + var/amount = tgui_input_number(user, "How long should our tail be?", "Worm Configurator", default = 3, min_value = 1) if (isnull(amount) || amount < 1 || QDELETED(head)) return head.AddComponent(/datum/component/mob_chain) diff --git a/code/modules/admin/adminmenu.dm b/code/modules/admin/adminmenu.dm deleted file mode 100644 index 9a93856aa4e..00000000000 --- a/code/modules/admin/adminmenu.dm +++ /dev/null @@ -1,11 +0,0 @@ -/datum/verbs/menu/Admin/Generate_list(client/C) - if (C.holder) - . = ..() - -/datum/verbs/menu/Admin/verb/playerpanel() - set name = "Player Panel" - set desc = "Player Panel" - set category = "Admin.Game" - if(usr.client.holder) - usr.client.holder.player_panel_new() - BLACKBOX_LOG_ADMIN_VERB("Player Panel New") diff --git a/code/modules/admin/callproc/callproc.dm b/code/modules/admin/callproc/callproc.dm index 1680304679e..823a4a9e64b 100644 --- a/code/modules/admin/callproc/callproc.dm +++ b/code/modules/admin/callproc/callproc.dm @@ -92,11 +92,8 @@ GLOBAL_PROTECT(AdminProcCallHandler) usr = lastusr handler.remove_caller(user) -/client/proc/callproc() - set category = "Debug" - set name = "Advanced ProcCall" - set waitfor = FALSE - callproc_blocking() +ADMIN_VERB(advanced_proc_call, R_DEBUG, "Advanced ProcCall", "Call a proc on any datum in the server.", ADMIN_CATEGORY_DEBUG) + user.callproc_blocking() /client/proc/callproc_blocking(list/get_retval) if(!check_rights(R_DEBUG)) @@ -230,37 +227,30 @@ GLOBAL_PROTECT(LastAdminCalledProc) return (GLOB.AdminProcCaller && GLOB.AdminProcCaller == usr?.client?.ckey) || (GLOB.AdminProcCallHandler && usr == GLOB.AdminProcCallHandler) #endif -/client/proc/callproc_datum(datum/A as null|area|mob|obj|turf) - set category = "Debug" - set name = "Atom ProcCall" - set waitfor = FALSE - - if(!check_rights(R_DEBUG)) - return - - var/procname = input("Proc name, eg: fake_blood","Proc:", null) as text|null +ADMIN_VERB_ONLY_CONTEXT_MENU(call_proc_datum, R_DEBUG, "Atom ProcCall", datum/thing as null|area|mob|obj|turf) + var/procname = input(user, "Proc name, eg: fake_blood","Proc:", null) as text|null if(!procname) return - if(!hascall(A,procname)) - to_chat(usr, "Error: callproc_datum(): type [A.type] has no proc named [procname].", confidential = TRUE) + if(!hascall(thing, procname)) + to_chat(user, "Error: callproc_datum(): type [thing.type] has no proc named [procname].", confidential = TRUE) return - var/list/lst = get_callproc_args() + var/list/lst = user.get_callproc_args() if(!lst) return - if(!A || !is_valid_src(A)) - to_chat(usr, span_warning("Error: callproc_datum(): owner of proc no longer exists."), confidential = TRUE) + if(!thing || !is_valid_src(thing)) + to_chat(user, span_warning("Error: callproc_datum(): owner of proc no longer exists."), confidential = TRUE) return - log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") - var/msg = "[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]." + log_admin("[key_name(user)] called [thing]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") + var/msg = "[key_name(user)] called [thing]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]." message_admins(msg) - admin_ticket_log(A, msg) + admin_ticket_log(thing, msg) BLACKBOX_LOG_ADMIN_VERB("Atom ProcCall") - var/returnval = WrapAdminProcCall(A, procname, lst) // Pass the lst as an argument list to the proc - . = get_callproc_returnval(returnval,procname) + var/returnval = WrapAdminProcCall(thing, procname, lst) // Pass the lst as an argument list to the proc + . = user.get_callproc_returnval(returnval,procname) if(.) - to_chat(usr, ., confidential = TRUE) + to_chat(user, ., confidential = TRUE) /client/proc/get_callproc_args() var/argnum = input("Number of arguments","Number:",0) as num|null diff --git a/code/modules/admin/force_event.dm b/code/modules/admin/force_event.dm index 20066547de9..519adbd8a9e 100644 --- a/code/modules/admin/force_event.dm +++ b/code/modules/admin/force_event.dm @@ -1,12 +1,6 @@ -///Allows an admin to force an event -/client/proc/forceEvent() - set name = "Trigger Event" - set category = "Admin.Events" - if(!holder || !check_rights(R_FUN)) - return - - holder.forceEvent() +ADMIN_VERB(force_event, R_FUN, "Trigger Event", "Forces an event to occur.", ADMIN_CATEGORY_EVENTS) + user.holder.forceEvent() ///Opens up the Force Event Panel /datum/admins/proc/forceEvent() diff --git a/code/modules/admin/greyscale_modify_menu.dm b/code/modules/admin/greyscale_modify_menu.dm index fd2db6d1ed3..89ad2fc8dd2 100644 --- a/code/modules/admin/greyscale_modify_menu.dm +++ b/code/modules/admin/greyscale_modify_menu.dm @@ -154,13 +154,13 @@ if("recolor") var/index = text2num(params["color_index"]) - var/new_color = lowertext(params["new_color"]) + var/new_color = LOWER_TEXT(params["new_color"]) if(split_colors[index] != new_color && (findtext(new_color, GLOB.is_color) || (unlocked && findtext(new_color, GLOB.is_alpha_color)))) split_colors[index] = new_color queue_refresh() if("recolor_from_string") - var/full_color_string = lowertext(params["color_string"]) + var/full_color_string = LOWER_TEXT(params["color_string"]) if(full_color_string != split_colors.Join() && ReadColorsFromString(full_color_string)) queue_refresh() diff --git a/code/modules/admin/known_alts.dm b/code/modules/admin/known_alts.dm index d6486f77bd7..4105c7f4edc 100644 --- a/code/modules/admin/known_alts.dm +++ b/code/modules/admin/known_alts.dm @@ -187,8 +187,5 @@ GLOBAL_DATUM_INIT(known_alts, /datum/known_alts, new) client << browse(html, "window=known_alts;size=700x400") -/datum/admins/proc/known_alts_panel() - set name = "Known Alts Panel" - set category = "Admin" - - GLOB.known_alts.show_panel(usr.client) +ADMIN_VERB(known_alts_panel, R_ADMIN, "Known Alts Panel", "View a panel of known alts.", ADMIN_CATEGORY_MAIN) + GLOB.known_alts.show_panel(user) diff --git a/code/modules/admin/outfit_manager.dm b/code/modules/admin/outfit_manager.dm index fcb41b3f2f1..f3ef7d2685c 100644 --- a/code/modules/admin/outfit_manager.dm +++ b/code/modules/admin/outfit_manager.dm @@ -1,18 +1,8 @@ -/client/proc/outfit_manager() - set category = "Debug" - set name = "Outfit Manager" - - if(!check_rights(R_DEBUG)) - return - var/datum/outfit_manager/ui = new(usr) - ui.ui_interact(usr) - +ADMIN_VERB(outfit_manager, R_DEBUG|R_ADMIN, "Outfit Manager", "View and edit outfits.", ADMIN_CATEGORY_DEBUG) + var/static/datum/outfit_manager/ui = new + ui.ui_interact(user.mob) /datum/outfit_manager - var/client/owner - -/datum/outfit_manager/New(user) - owner = CLIENT_FROM_VAR(user) /datum/outfit_manager/ui_state(mob/user) return GLOB.admin_state @@ -53,24 +43,24 @@ switch(action) if("new") - owner.open_outfit_editor(new /datum/outfit) + ui.user.client.open_outfit_editor(new /datum/outfit) if("load") - owner.holder.load_outfit(owner.mob) + ui.user.client.holder.load_outfit(ui.user) if("copy") - var/datum/outfit/outfit = tgui_input_list(owner, "Pick an outfit to copy from", "Outfit Manager", subtypesof(/datum/outfit)) + var/datum/outfit/outfit = tgui_input_list(ui.user, "Pick an outfit to copy from", "Outfit Manager", subtypesof(/datum/outfit)) if(isnull(outfit)) return if(!ispath(outfit)) return - owner.open_outfit_editor(new outfit) + ui.user.client.open_outfit_editor(new outfit) var/datum/outfit/target_outfit = locate(params["outfit"]) if(!istype(target_outfit)) return switch(action) //wow we're switching through action again this is horrible optimization smh if("edit") - owner.open_outfit_editor(target_outfit) + ui.user.client.open_outfit_editor(target_outfit) if("save") - owner.holder.save_outfit(owner.mob, target_outfit) + ui.user.client.holder.save_outfit(ui.user, target_outfit) if("delete") - owner.holder.delete_outfit(owner.mob, target_outfit) + ui.user.client.holder.delete_outfit(ui.user, target_outfit) diff --git a/code/modules/admin/painting_manager.dm b/code/modules/admin/painting_manager.dm index bd7d28fb73f..7a8bd7127a4 100644 --- a/code/modules/admin/painting_manager.dm +++ b/code/modules/admin/painting_manager.dm @@ -1,11 +1,6 @@ -/datum/admins/proc/paintings_manager() - set name = "Paintings Manager" - set category = "Admin" - - if(!check_rights(R_ADMIN)) - return - var/datum/paintings_manager/ui = new(usr) - ui.ui_interact(usr) +ADMIN_VERB(painting_manager, R_ADMIN, "Paintings Manager", "View and redact paintings.", ADMIN_CATEGORY_MAIN) + var/static/datum/paintings_manager/ui = new + ui.ui_interact(user.mob) /// Painting Admin Management Panel /datum/paintings_manager diff --git a/code/modules/admin/permissionedit.dm b/code/modules/admin/permissionedit.dm index cf816fef8a7..e92ab1729e2 100644 --- a/code/modules/admin/permissionedit.dm +++ b/code/modules/admin/permissionedit.dm @@ -1,10 +1,6 @@ -/client/proc/edit_admin_permissions() - set category = "Admin" - set name = "Permissions Panel" - set desc = "Edit admin permissions" - if(!check_rights(R_PERMISSIONS)) - return - usr.client.holder.edit_admin_permissions() + +ADMIN_VERB(edit_admin_permissions, R_PERMISSIONS, "Permissions Panel", "Edit admin permissions.", ADMIN_CATEGORY_MAIN) + user.holder.edit_admin_permissions() /datum/admins/proc/edit_admin_permissions(action, target, operation, page) if(!check_rights(R_PERMISSIONS)) diff --git a/code/modules/admin/sound_emitter.dm b/code/modules/admin/sound_emitter.dm index 4786e0ad7c1..d697537c6df 100644 --- a/code/modules/admin/sound_emitter.dm +++ b/code/modules/admin/sound_emitter.dm @@ -51,10 +51,13 @@ return edit_emitter(user) -/obj/effect/sound_emitter/AltClick(mob/user) - if(check_rights_for(user.client, R_SOUND)) - activate(user) - to_chat(user, span_notice("Sound emitter activated."), confidential = TRUE) +/obj/effect/sound_emitter/click_alt(mob/user) + if(!check_rights_for(user.client, R_SOUND)) + return CLICK_ACTION_BLOCKING + + activate(user) + to_chat(user, span_notice("Sound emitter activated."), confidential = TRUE) + return CLICK_ACTION_SUCCESS /obj/effect/sound_emitter/proc/edit_emitter(mob/user) var/dat = "" diff --git a/code/modules/admin/sql_ban_system.dm b/code/modules/admin/sql_ban_system.dm index a57f29b3150..30c657e6ab5 100644 --- a/code/modules/admin/sql_ban_system.dm +++ b/code/modules/admin/sql_ban_system.dm @@ -638,7 +638,7 @@ duration = text2num(duration) if (!(interval in list("SECOND", "MINUTE", "HOUR", "DAY", "WEEK", "MONTH", "YEAR"))) interval = "MINUTE" - var/time_message = "[duration] [lowertext(interval)]" //no DisplayTimeText because our duration is of variable interval type + var/time_message = "[duration] [LOWER_TEXT(interval)]" //no DisplayTimeText because our duration is of variable interval type if(duration > 1) //pluralize the interval if necessary time_message += "s" var/is_server_ban = (roles_to_ban[1] == "Server") diff --git a/code/modules/admin/sql_message_system.dm b/code/modules/admin/sql_message_system.dm index 88ab09de6d3..9dee7ef38ee 100644 --- a/code/modules/admin/sql_message_system.dm +++ b/code/modules/admin/sql_message_system.dm @@ -755,18 +755,4 @@ notesfile.cd = "/" notesfile.dir.Remove(ckey) -/*alternatively this proc can be run once to pass through every note and attempt to convert it before deleting the file, if done then AUTOCONVERT_NOTES should be turned off -this proc can take several minutes to execute fully if converting and cause DD to hang if converting a lot of notes; it's not advised to do so while a server is live -/proc/mass_convert_notes() - to_chat(world, "Beginning mass note conversion", confidential = TRUE) - var/savefile/notesfile = new(NOTESFILE) - if(!notesfile) - log_game("Error: Cannot access [NOTESFILE]") - return - notesfile.cd = "/" - for(var/ckey in notesfile.dir) - convert_notes_sql(ckey) - to_chat(world, "Deleting NOTESFILE", confidential = TRUE) - fdel(NOTESFILE) - to_chat(world, "Finished mass note conversion, remember to turn off AUTOCONVERT_NOTES", confidential = TRUE)*/ #undef NOTESFILE diff --git a/code/modules/admin/stickyban.dm b/code/modules/admin/stickyban.dm index 537e0b92acb..fede9724ab1 100644 --- a/code/modules/admin/stickyban.dm +++ b/code/modules/admin/stickyban.dm @@ -481,10 +481,5 @@ . = list2params(.) - -/client/proc/stickybanpanel() - set name = "Sticky Ban Panel" - set category = "Admin" - if (!holder) - return - holder.stickyban_show() +ADMIN_VERB(panel_sticky_ban, R_BAN, "Sticky Ban Panel", "List and manage sticky bans.", ADMIN_CATEGORY_MAIN) + user.holder.stickyban_show() diff --git a/code/modules/admin/tag.dm b/code/modules/admin/tag.dm index 64c6c16fc40..e52112eba14 100644 --- a/code/modules/admin/tag.dm +++ b/code/modules/admin/tag.dm @@ -49,21 +49,14 @@ [X.getToxLoss()] \ [X.getOxyLoss()]" -/// Display all of the tagged datums -/datum/admins/proc/display_tags() - set category = "Admin.Game" - set name = "View Tags" - - if (!istype(src, /datum/admins)) - src = usr.client.holder - if (!istype(src, /datum/admins)) - to_chat(usr, "Error: you are not an admin!", confidential = TRUE) - return - +ADMIN_VERB(display_tags, R_ADMIN, "View Tags", "Display all of the tagged datums.", ADMIN_CATEGORY_GAME) var/index = 0 var/list/dat = list("
Tag Menu

") - dat += "
Refresh
" + var/list/tagged_datums = user.holder.tagged_datums + var/list/marked_datum = user.holder.marked_datum + + dat += "
Refresh
" if(LAZYLEN(tagged_datums)) for(var/datum/iter_datum as anything in tagged_datums) index++ @@ -71,7 +64,7 @@ if(isnull(iter_datum)) dat += "\t[index]: Null reference - Check runtime logs!" - stack_trace("Null datum found in tagged datum menu! User: [usr]") + stack_trace("Null datum found in tagged datum menu! User: [user]") continue else if(iscarbon(iter_datum)) var/mob/living/carbon/resolved_carbon = iter_datum @@ -99,7 +92,7 @@ dat += "No datums tagged :(" dat = dat.Join("
") - usr << browse(dat, "window=tag;size=800x480") + user << browse(dat, "window=tag;size=800x480") #undef TAG_DEL #undef TAG_MARK diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 5b644902ffe..dfbf55f79e1 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -180,8 +180,7 @@ to_chat(usr, "[shuttle_console] was [shuttle_console.admin_controlled ? "locked" : "unlocked"].", confidential = TRUE) else if(href_list["delay_round_end"]) - // Permissions are checked in delay_round_end - delay_round_end() + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/delay_round_end) else if(href_list["undelay_round_end"]) if(!check_rights(R_SERVER)) @@ -776,21 +775,10 @@ our_mob.AIize(our_mob.client, move) else if(href_list["makerobot"]) - if(!check_rights(R_SPAWN)) - return - - var/mob/our_mob = locate(href_list["makerobot"]) - if(!istype(our_mob)) - return - if(iscyborg(our_mob)) - to_chat(usr, "That's already a cyborg.", confidential = TRUE) - return - - usr.client.cmd_admin_robotize(our_mob) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/cmd_admin_robotize, locate(href_list["makerobot"])) else if(href_list["adminplayeropts"]) - var/mob/M = locate(href_list["adminplayeropts"]) - show_player_panel(M) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/show_player_panel, locate(href_list["adminplayeropts"])) else if(href_list["ppbyckey"]) var/target_ckey = href_list["ppbyckey"] @@ -805,7 +793,7 @@ return to_chat(usr, span_notice("Jumping to [target_ckey]'s new mob: [target_mob]!")) - show_player_panel(target_mob) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/show_player_panel, target_mob) else if(href_list["adminplayerobservefollow"]) if(!isobserver(usr) && !check_rights(R_ADMIN)) @@ -822,20 +810,13 @@ AM.forceMove(get_turf(usr)) else if(href_list["adminplayerobservecoodjump"]) - if(!isobserver(usr) && !check_rights(R_ADMIN)) - return - if(isnewplayer(usr)) - return - - var/x = text2num(href_list["X"]) - var/y = text2num(href_list["Y"]) - var/z = text2num(href_list["Z"]) - - var/client/C = usr.client - if(!isobserver(usr)) - C.admin_ghost() - sleep(0.2 SECONDS) - C.jumptocoord(x,y,z) + return SSadmin_verbs.dynamic_invoke_verb( + usr, + /datum/admin_verb/jump_to_coord, + text2num(href_list["X"]), + text2num(href_list["Y"]), + text2num(href_list["Z"]), + ) else if(href_list["adminchecklaws"]) if(!check_rights(R_ADMIN)) @@ -1035,15 +1016,7 @@ give_admin_popup(target, owner, message) else if(href_list["adminsmite"]) - if(!check_rights(R_ADMIN|R_FUN)) - return - - var/mob/living/carbon/human/H = locate(href_list["adminsmite"]) in GLOB.mob_list - if(!H || !istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human", confidential = TRUE) - return - - usr.client.smite(H) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/admin_smite, locate(href_list["adminsmite"])) else if(href_list["CentComReply"]) if(!check_rights(R_ADMIN)) @@ -1072,42 +1045,21 @@ var/obj/item/station_charter/charter = locate(href_list["reject_custom_name"]) if(istype(charter)) charter.reject_proposed(usr) - else if(href_list["jumpto"]) - if(!isobserver(usr) && !check_rights(R_ADMIN)) - return - var/mob/M = locate(href_list["jumpto"]) - usr.client.jumptomob(M) + else if(href_list["jumpto"]) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/jump_to_mob, locate(href_list["jumpto"])) else if(href_list["getmob"]) - if(!check_rights(R_ADMIN)) - return - - if(tgui_alert(usr, "Confirm?", "Message", list("Yes", "No")) != "Yes") - return - var/mob/M = locate(href_list["getmob"]) - usr.client.Getmob(M) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/get_mob, locate(href_list["getmob"])) else if(href_list["sendmob"]) - if(!check_rights(R_ADMIN)) - return - - var/mob/M = locate(href_list["sendmob"]) - usr.client.sendmob(M) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/send_mob, locate(href_list["sendmob"])) else if(href_list["narrateto"]) - if(!check_rights(R_ADMIN)) - return - - var/mob/M = locate(href_list["narrateto"]) - usr.client.cmd_admin_direct_narrate(M) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/cmd_admin_direct_narrate, locate(href_list["narrateto"])) else if(href_list["subtlemessage"]) - if(!check_rights(R_ADMIN)) - return - - var/mob/M = locate(href_list["subtlemessage"]) - usr.client.cmd_admin_subtle_message(M) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/cmd_admin_subtle_message, locate(href_list["subtlemessage"])) else if(href_list["playsoundto"]) if(!check_rights(R_SOUND)) @@ -1116,7 +1068,7 @@ var/mob/M = locate(href_list["playsoundto"]) var/S = input("", "Select a sound file",) as null|sound if(S) - usr.client.play_direct_mob_sound(S, M) + SSadmin_verbs.dynamic_invoke_verb(usr.client, /datum/admin_verb/play_direct_mob_sound, S, M) else if(href_list["individuallog"]) if(!check_rights(R_ADMIN)) @@ -1155,7 +1107,8 @@ else D.traitor_panel() else - show_traitor_panel(M) + SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/show_traitor_panel, M) + return else if(href_list["skill"]) if(!check_rights(R_ADMIN)) @@ -1175,17 +1128,11 @@ else to_chat(usr, "This can only be used on instances of type /mob and /mind", confidential = TRUE) return - show_skill_panel(target_mind) + SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/show_skill_panel, target_mind) + return else if(href_list["borgpanel"]) - if(!check_rights(R_ADMIN)) - return - - var/mob/M = locate(href_list["borgpanel"]) - if(!iscyborg(M)) - to_chat(usr, "This can only be used on cyborgs", confidential = TRUE) - else - open_borgopanel(M) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/borg_panel, locate(href_list["borgpanel"])) else if(href_list["initmind"]) if(!check_rights(R_ADMIN)) @@ -1357,9 +1304,7 @@ return else if(href_list["check_antagonist"]) - if(!check_rights(R_ADMIN)) - return - usr.client.check_antagonists() + SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/check_antagonists) else if(href_list["kick_all_from_lobby"]) if(!check_rights(R_ADMIN)) @@ -1429,7 +1374,7 @@ log_admin("[key_name(usr)] turned a Lag Switch measure at index ([switch_index]) [LAZYACCESS(SSlag_switch.measures, switch_index) ? "ON" : "OFF"]") message_admins("[key_name_admin(usr)] turned a Lag Switch measure [LAZYACCESS(SSlag_switch.measures, switch_index) ? "ON" : "OFF"]") - src.show_lag_switch_panel() + SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/lag_switch_panel) else if(href_list["change_lag_switch_option"]) if(!check_rights(R_ADMIN)) @@ -1458,7 +1403,7 @@ log_admin("[key_name(usr)] set the Lag Switch slowmode cooldown to [new_num] seconds.") message_admins("[key_name_admin(usr)] set the Lag Switch slowmode cooldown to [new_num] seconds.") - src.show_lag_switch_panel() + SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/lag_switch_panel) else if(href_list["viewruntime"]) var/datum/error_viewer/error_viewer = locate(href_list["viewruntime"]) @@ -1577,13 +1522,7 @@ toggle_id_ctf(usr, CTF_GHOST_CTF_GAME_ID) else if(href_list["rebootworld"]) - if(!check_rights(R_ADMIN)) - return - var/confirm = tgui_alert(usr,"Are you sure you want to reboot the server?", "Confirm Reboot", list("Yes", "No")) - if(confirm == "No") - return - if(confirm == "Yes") - restart() + SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/restart) else if(href_list["check_teams"]) if(!check_rights(R_ADMIN)) @@ -1802,9 +1741,7 @@ return remove_tagged_datum(datum_to_remove) else if(href_list["show_tags"]) - if(!check_rights(R_ADMIN)) - return - return display_tags() + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/display_tags) else if(href_list["mark_datum"]) if(!check_rights(R_ADMIN)) @@ -1860,7 +1797,4 @@ web_sound(usr, link_url, credit) else if(href_list["debug_z_levels"]) - if(!check_rights(R_DEBUG)) - return - - owner.debug_z_levels() + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/debug_z_levels) diff --git a/code/modules/admin/trophy_manager.dm b/code/modules/admin/trophy_manager.dm index 6a45afb8e45..5ad703b0994 100644 --- a/code/modules/admin/trophy_manager.dm +++ b/code/modules/admin/trophy_manager.dm @@ -1,11 +1,6 @@ -/datum/admins/proc/trophy_manager() - set name = "Trophy Manager" - set category = "Admin" - - if(!check_rights(R_ADMIN)) - return - var/datum/trophy_manager/ui = new(usr) - ui.ui_interact(usr) +ADMIN_VERB(trophy_manager, R_ADMIN, "Trophy Manager", "View all trophies.", ADMIN_CATEGORY_MAIN) + var/static/datum/trophy_manager/ui = new + ui.ui_interact(user.mob) /// Trophy Admin Management Panel /datum/trophy_manager diff --git a/code/modules/admin/verb_datums/_admin_verb_datum.dm b/code/modules/admin/verb_datums/_admin_verb_datum.dm new file mode 100644 index 00000000000..6255d962c40 --- /dev/null +++ b/code/modules/admin/verb_datums/_admin_verb_datum.dm @@ -0,0 +1,27 @@ +GENERAL_PROTECT_DATUM(/datum/admin_verb) + +/** + * This is the admin verb datum. It is used to store the verb's information and handle the verb's functionality. + * All of this is setup for you, and you should not be defining this manually. + * That means you reader. + */ +/datum/admin_verb + var/name //! The name of the verb. + var/description //! The description of the verb. + var/category //! The category of the verb. + var/permissions //! The permissions required to use the verb. + var/visibility_flag //! The flag that determines if the verb is visible. + VAR_PROTECTED/verb_path //! The path to the verb proc. + +/datum/admin_verb/Destroy(force) + if(!force) + return QDEL_HINT_LETMELIVE + return ..() + +/// Assigns the verb to the admin. +/datum/admin_verb/proc/assign_to_client(client/admin) + add_verb(admin, verb_path) + +/// Unassigns the verb from the admin. +/datum/admin_verb/proc/unassign_from_client(client/admin) + remove_verb(admin, verb_path) diff --git a/code/modules/admin/verb_datums/_admin_verb_holder.dm b/code/modules/admin/verb_datums/_admin_verb_holder.dm new file mode 100644 index 00000000000..e69de29bb2d diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm index 17047dbcd68..36db4fa8bc4 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm @@ -195,20 +195,15 @@ state = SDQL2_STATE_ERROR;\ CRASH("SDQL2 fatal error");}; -/client/proc/SDQL2_query(query_text as message) - set category = "Debug" - if(!check_rights(R_DEBUG)) //Shouldn't happen... but just to be safe. - message_admins(span_danger("ERROR: Non-admin [key_name(usr)] attempted to execute a SDQL query!")) - usr.log_message("non-admin attempted to execute a SDQL query!", LOG_ADMIN) - return FALSE - var/prompt = tgui_alert(usr, "Run SDQL2 Query?", "SDQL2", list("Yes", "Cancel")) +ADMIN_VERB(sdql2_query, R_DEBUG, "SDQL2 Query", "Run a SDQL2 query.", ADMIN_CATEGORY_DEBUG, query_text as message) + var/prompt = tgui_alert(user, "Run SDQL2 Query?", "SDQL2", list("Yes", "Cancel")) if (prompt != "Yes") return - var/list/results = world.SDQL2_query(query_text, key_name_admin(usr), "[key_name(usr)]") + var/list/results = world.SDQL2_query(query_text, key_name_admin(user), "[key_name(user)]") if(length(results) == 3) for(var/I in 1 to 3) - to_chat(usr, span_admin(results[I]), confidential = TRUE) - SSblackbox.record_feedback("nested tally", "SDQL query", 1, list(ckey, query_text)) + to_chat(user, span_admin(results[I]), confidential = TRUE) + SSblackbox.record_feedback("nested tally", "SDQL query", 1, list(user.ckey, query_text)) /world/proc/SDQL2_query(query_text, log_entry1, log_entry2, silent = FALSE) var/query_log = "executed SDQL query(s): \"[query_text]\"." @@ -1027,7 +1022,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/sdql2_vv_all, new(null return null else if(expression [start] == "{" && long) - if(lowertext(copytext(expression[start + 1], 1, 3)) != "0x") //3 == length("0x") + 1 + if(LOWER_TEXT(copytext(expression[start + 1], 1, 3)) != "0x") //3 == length("0x") + 1 to_chat(usr, span_danger("Invalid pointer syntax: [expression[start + 1]]"), confidential = TRUE) return null var/datum/located = locate("\[[expression[start + 1]]]") diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm index 58a18e1a936..eb262339841 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm @@ -109,7 +109,7 @@ return null /datum/sdql_parser/proc/tokenl(i) - return lowertext(token(i)) + return LOWER_TEXT(token(i)) /datum/sdql_parser/proc/query_options(i, list/node) var/list/options = list() @@ -624,7 +624,7 @@ node += "null" i++ - else if(lowertext(copytext(token(i), 1, 3)) == "0x" && isnum(hex2num(copytext(token(i), 3))))//3 == length("0x") + 1 + else if(LOWER_TEXT(copytext(token(i), 1, 3)) == "0x" && isnum(hex2num(copytext(token(i), 3))))//3 == length("0x") + 1 node += hex2num(copytext(token(i), 3)) i++ diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm index 06c19ce5c91..bc74347475a 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm @@ -81,8 +81,8 @@ /proc/_log(X, Y) return log(X, Y) -/proc/_lowertext(T) - return lowertext(T) +/proc/_LOWER_TEXT(T) + return LOWER_TEXT(T) /proc/_matrix(a, b, c, d, e, f) return matrix(a, b, c, d, e, f) diff --git a/code/modules/admin/verbs/admin.dm b/code/modules/admin/verbs/admin.dm index d78014e84d2..f6517b13564 100644 --- a/code/modules/admin/verbs/admin.dm +++ b/code/modules/admin/verbs/admin.dm @@ -1,15 +1,5 @@ -// Admin Tab - Admin Verbs - -/client/proc/show_tip() - set category = "Admin" - set name = "Show Tip" - set desc = "Sends a tip (that you specify) to all players. After all \ - you're the experienced player here." - - if(!check_rights(R_ADMIN)) - return - - var/input = input(usr, "Please specify your tip that you want to send to the players.", "Tip", "") as message|null +ADMIN_VERB(show_tip, R_ADMIN, "Show Tip", "Sends a tip to all players.", ADMIN_CATEGORY_MAIN) + var/input = input(user, "Please specify your tip that you want to send to the players.", "Tip", "") as message|null if(!input) return @@ -22,44 +12,34 @@ else SSticker.selected_tip = input - message_admins("[key_name_admin(usr)] sent a tip of the round.") - log_admin("[key_name(usr)] sent \"[input]\" as the Tip of the Round.") + message_admins("[key_name_admin(user)] sent a tip of the round.") + log_admin("[key_name(user)] sent \"[input]\" as the Tip of the Round.") BLACKBOX_LOG_ADMIN_VERB("Show Tip") -/datum/admins/proc/announce() - set category = "Admin" - set name = "Announce" - set desc="Announce your desires to the world" - if(!check_rights(0)) +ADMIN_VERB(announce, R_ADMIN, "Announce", "Announce your desires to the world.", ADMIN_CATEGORY_MAIN) + var/message = input(user, "Global message to send:", "Admin Announce") as message|null + if(!message) return - var/message = input("Global message to send:", "Admin Announce", null, null) as message|null - if(message) - if(!check_rights(R_SERVER,0)) - message = adminscrub(message,500) - send_ooc_announcement(message, "From [usr.client.holder.fakekey ? "Administrator" : usr.key]") - log_admin("Announce: [key_name(usr)] : [message]") + if(!user.holder.check_for_rights(R_SERVER)) + message = adminscrub(message,500) + send_ooc_announcement(message, "From [user.holder.fakekey ? "Administrator" : user.key]") + log_admin("Announce: [key_name(user)] : [message]") BLACKBOX_LOG_ADMIN_VERB("Announce") -/datum/admins/proc/unprison(mob/M in GLOB.mob_list) - set category = "Admin" - set name = "Unprison" - if (is_centcom_level(M.z)) - SSjob.SendToLateJoin(M) - message_admins("[key_name_admin(usr)] has unprisoned [key_name_admin(M)]") - log_admin("[key_name(usr)] has unprisoned [key_name(M)]") - else - tgui_alert(usr,"[M.name] is not prisoned.") - BLACKBOX_LOG_ADMIN_VERB("Unprison") - -/client/proc/cmd_admin_check_player_exp() //Allows admins to determine who the newer players are. - set category = "Admin" - set name = "Player Playtime" - if(!check_rights(R_ADMIN)) +ADMIN_VERB(unprison, R_ADMIN, "UnPrison", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/prisoner in GLOB.mob_list) + if(!is_centcom_level(prisoner.z)) + tgui_alert(user, "[prisoner.name] is not prisoned.") return + SSjob.SendToLateJoin(prisoner) + message_admins("[key_name_admin(user)] has unprisoned [key_name_admin(prisoner)]") + log_admin("[key_name(user)] has unprisoned [key_name(prisoner)]") + BLACKBOX_LOG_ADMIN_VERB("Unprison") + +ADMIN_VERB(cmd_admin_check_player_exp, R_ADMIN, "Player Playtime", "View player playtime.", ADMIN_CATEGORY_MAIN) if(!CONFIG_GET(flag/use_exp_tracking)) - to_chat(usr, span_warning("Tracking is disabled in the server configuration file."), confidential = TRUE) + to_chat(user, span_warning("Tracking is disabled in the server configuration file."), confidential = TRUE) return var/list/msg = list() @@ -67,7 +47,7 @@ for(var/client/client in sort_list(GLOB.clients, GLOBAL_PROC_REF(cmp_playtime_asc))) msg += "
  • [ADMIN_PP(client.mob)] [key_name_admin(client)]: " + client.get_exp_living() + "
  • " msg += "" - src << browse(msg.Join(), "window=Player_playtime_check") + user << browse(msg.Join(), "window=Player_playtime_check") /client/proc/trigger_centcom_recall() if(!check_rights(R_ADMIN)) @@ -164,23 +144,18 @@ /////////////////////////////////////////////////////////////////////////////////////////////// -/client/proc/cmd_admin_drop_everything(mob/M in GLOB.mob_list) - set category = null - set name = "Drop Everything" - if(!check_rights(R_ADMIN)) - return - - var/confirm = tgui_alert(usr, "Make [M] drop everything?", "Message", list("Yes", "No")) +ADMIN_VERB(drop_everything, R_ADMIN, "Drop Everything", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/dropee in GLOB.mob_list) + var/confirm = tgui_alert(user, "Make [dropee] drop everything?", "Message", list("Yes", "No")) if(confirm != "Yes") return - M.drop_everything(del_on_drop = FALSE, force = TRUE, del_if_nodrop = TRUE) - M.regenerate_icons() + dropee.drop_everything(del_on_drop = FALSE, force = TRUE, del_if_nodrop = TRUE) + dropee.regenerate_icons() - log_admin("[key_name(usr)] made [key_name(M)] drop everything!") - var/msg = "[key_name_admin(usr)] made [ADMIN_LOOKUPFLW(M)] drop everything!" + log_admin("[key_name(user)] made [key_name(dropee)] drop everything!") + var/msg = "[key_name_admin(user)] made [ADMIN_LOOKUPFLW(dropee)] drop everything!" message_admins(msg) - admin_ticket_log(M, msg) + admin_ticket_log(dropee, msg) BLACKBOX_LOG_ADMIN_VERB("Drop Everything") /proc/cmd_admin_mute(whom, mute_type, automute = 0) diff --git a/code/modules/admin/verbs/admin_newscaster.dm b/code/modules/admin/verbs/admin_newscaster.dm index 2f6870394c2..0439cfa8811 100644 --- a/code/modules/admin/verbs/admin_newscaster.dm +++ b/code/modules/admin/verbs/admin_newscaster.dm @@ -1,17 +1,6 @@ -/datum/admins/proc/access_news_network() //MARKER - set category = "Admin.Events" - set name = "Access Newscaster Network" - set desc = "Allows you to view, add and edit news feeds." - - if (!istype(src, /datum/admins)) - src = usr.client.holder - if (!istype(src, /datum/admins)) - to_chat(usr, "Error: you are not an admin!", confidential = TRUE) - return - +ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows you to view, add, and edit news feeds.", ADMIN_CATEGORY_EVENTS) var/datum/newspanel/new_newspanel = new - - new_newspanel.ui_interact(usr) + new_newspanel.ui_interact(user.mob) /datum/newspanel ///What newscaster channel is currently being viewed by the player? diff --git a/code/modules/admin/verbs/adminevents.dm b/code/modules/admin/verbs/adminevents.dm index 26219353cce..32e49cf2e73 100644 --- a/code/modules/admin/verbs/adminevents.dm +++ b/code/modules/admin/verbs/adminevents.dm @@ -1,37 +1,24 @@ // Admin Tab - Event Verbs -/client/proc/cmd_admin_subtle_message(mob/M in GLOB.mob_list) - set category = "Admin.Events" - set name = "Subtle Message" - - if(!ismob(M)) - return - if(!check_rights(R_ADMIN)) - return - - message_admins("[key_name_admin(src)] has started answering [ADMIN_LOOKUPFLW(M)]'s prayer.") - var/msg = input("Message:", "Subtle PM to [M.key]") as text|null +ADMIN_VERB_AND_CONTEXT_MENU(cmd_admin_subtle_message, R_ADMIN, "Subtle Message", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/target in world) + message_admins("[key_name_admin(user)] has started answering [ADMIN_LOOKUPFLW(target)]'s prayer.") + var/msg = input(user, "Message:", "Subtle PM to [target.key]") as text|null if(!msg) - message_admins("[key_name_admin(src)] decided not to answer [ADMIN_LOOKUPFLW(M)]'s prayer") + message_admins("[key_name_admin(user)] decided not to answer [ADMIN_LOOKUPFLW(target)]'s prayer") return - if(usr) - if (usr.client) - if(usr.client.holder) - M.balloon_alert(M, "you hear a voice") - to_chat(M, "You hear a voice in your head... [msg]", confidential = TRUE) - log_admin("SubtlePM: [key_name(usr)] -> [key_name(M)] : [msg]") - msg = span_adminnotice(" SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] : [msg]") + target.balloon_alert(target, "you hear a voice") + to_chat(target, "You hear a voice in your head... [msg]", confidential = TRUE) + + log_admin("SubtlePM: [key_name(user)] -> [key_name(target)] : [msg]") + msg = span_adminnotice(" SubtleMessage: [key_name_admin(user)] -> [key_name_admin(target)] : [msg]") message_admins(msg) - admin_ticket_log(M, msg) + admin_ticket_log(target, msg) BLACKBOX_LOG_ADMIN_VERB("Subtle Message") -/client/proc/cmd_admin_headset_message(mob/M in GLOB.mob_list) - set category = "Admin.Events" - set name = "Headset Message" - - admin_headset_message(M) +ADMIN_VERB_AND_CONTEXT_MENU(cmd_admin_headset_message, R_ADMIN, "Headset Message", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/target in world) + user.admin_headset_message(target) /client/proc/admin_headset_message(mob/target in GLOB.mob_list, sender = null) var/mob/living/carbon/human/human_recipient @@ -73,102 +60,64 @@ BLACKBOX_LOG_ADMIN_VERB("Headset Message") -/client/proc/cmd_admin_world_narrate() - set category = "Admin.Events" - set name = "Global Narrate" - - if(!check_rights(R_ADMIN)) - return - - var/msg = input("Message:", "Enter the text you wish to appear to everyone:") as text|null - +ADMIN_VERB(cmd_admin_world_narrate, R_ADMIN, "Global Narrate", "Send a direct narration to all connected players.", ADMIN_CATEGORY_EVENTS) + var/msg = input(user, "Message:", "Enter the text you wish to appear to everyone:") as text|null if (!msg) return to_chat(world, "[msg]", confidential = TRUE) - log_admin("GlobalNarrate: [key_name(usr)] : [msg]") - message_admins(span_adminnotice("[key_name_admin(usr)] Sent a global narrate")) + log_admin("GlobalNarrate: [key_name(user)] : [msg]") + message_admins(span_adminnotice("[key_name_admin(user)] Sent a global narrate")) BLACKBOX_LOG_ADMIN_VERB("Global Narrate") -/client/proc/cmd_admin_local_narrate(atom/A) - set category = "Admin.Events" - set name = "Local Narrate" - - if(!check_rights(R_ADMIN)) - return - if(!A) - return - var/range = input("Range:", "Narrate to mobs within how many tiles:", 7) as num|null +ADMIN_VERB_AND_CONTEXT_MENU(cmd_admin_local_narrate, R_ADMIN, "Local Narrate", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, atom/locale in world) + var/range = input(user, "Range:", "Narrate to mobs within how many tiles:", 7) as num|null if(!range) return - var/msg = input("Message:", "Enter the text you wish to appear to everyone within view:") as text|null + var/msg = input(user, "Message:", "Enter the text you wish to appear to everyone within view:") as text|null if (!msg) return - for(var/mob/M in view(range,A)) + for(var/mob/M in view(range, locale)) to_chat(M, msg, confidential = TRUE) - log_admin("LocalNarrate: [key_name(usr)] at [AREACOORD(A)]: [msg]") - message_admins(span_adminnotice(" LocalNarrate: [key_name_admin(usr)] at [ADMIN_VERBOSEJMP(A)]: [msg]
    ")) + log_admin("LocalNarrate: [key_name(user)] at [AREACOORD(locale)]: [msg]") + message_admins(span_adminnotice(" LocalNarrate: [key_name_admin(user)] at [ADMIN_VERBOSEJMP(locale)]: [msg]
    ")) BLACKBOX_LOG_ADMIN_VERB("Local Narrate") -/client/proc/cmd_admin_direct_narrate(mob/M) - set category = "Admin.Events" - set name = "Direct Narrate" - - if(!check_rights(R_ADMIN)) - return - - if(!M) - M = input("Direct narrate to whom?", "Active Players") as null|anything in GLOB.player_list - - if(!M) - return - - var/msg = input("Message:", "Enter the text you wish to appear to your target:") as text|null +ADMIN_VERB_AND_CONTEXT_MENU(cmd_admin_direct_narrate, R_ADMIN, "Direct Narrate", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/target) + var/msg = input(user, "Message:", "Enter the text you wish to appear to your target:") as text|null if( !msg ) return - to_chat(M, msg, confidential = TRUE) - log_admin("DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]") - msg = span_adminnotice(" DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]
    ") + to_chat(target, msg, confidential = TRUE) + log_admin("DirectNarrate: [key_name(user)] to ([key_name(target)]): [msg]") + msg = span_adminnotice(" DirectNarrate: [key_name_admin(user)] to ([key_name_admin(target)]): [msg]
    ") message_admins(msg) - admin_ticket_log(M, msg) + admin_ticket_log(target, msg) BLACKBOX_LOG_ADMIN_VERB("Direct Narrate") -/client/proc/cmd_admin_add_freeform_ai_law() - set category = "Admin.Events" - set name = "Add Custom AI law" - - if(!check_rights(R_ADMIN)) - return - - var/input = input(usr, "Please enter anything you want the AI to do. Anything. Serious.", "What?", "") as text|null +ADMIN_VERB(cmd_admin_add_freeform_ai_law, R_ADMIN, "Add Custom AI Law", "Add a custom law to the Silicons.", ADMIN_CATEGORY_EVENTS) + var/input = input(user, "Please enter anything you want the AI to do. Anything. Serious.", "What?", "") as text|null if(!input) return - log_admin("Admin [key_name(usr)] has added a new AI law - [input]") - message_admins("Admin [key_name_admin(usr)] has added a new AI law - [input]") + log_admin("Admin [key_name(user)] has added a new AI law - [input]") + message_admins("Admin [key_name_admin(user)] has added a new AI law - [input]") - var/show_log = tgui_alert(usr, "Show ion message?", "Message", list("Yes", "No")) + var/show_log = tgui_alert(user, "Show ion message?", "Message", list("Yes", "No")) var/announce_ion_laws = (show_log == "Yes" ? 100 : 0) - var/datum/round_event/ion_storm/add_law_only/ion = new() + var/datum/round_event/ion_storm/add_law_only/ion = new ion.announce_chance = announce_ion_laws ion.ionMessage = input BLACKBOX_LOG_ADMIN_VERB("Add Custom AI Law") -/client/proc/admin_call_shuttle() - set category = "Admin.Events" - set name = "Call Shuttle" - +ADMIN_VERB(call_shuttle, R_ADMIN, "Call Shuttle", "Force a shuttle call with additional modifiers.", ADMIN_CATEGORY_EVENTS) if(EMERGENCY_AT_LEAST_DOCKED) return - if(!check_rights(R_ADMIN)) - return - - var/confirm = tgui_alert(usr, "You sure?", "Confirm", list("Yes", "Yes (No Recall)", "No")) + var/confirm = tgui_alert(user, "You sure?", "Confirm", list("Yes", "Yes (No Recall)", "No")) switch(confirm) if(null, "No") return @@ -178,46 +127,30 @@ SSshuttle.emergency.request() BLACKBOX_LOG_ADMIN_VERB("Call Shuttle") - log_admin("[key_name(usr)] admin-called the emergency shuttle.") - message_admins(span_adminnotice("[key_name_admin(usr)] admin-called the emergency shuttle[confirm == "Yes (No Recall)" ? " (non-recallable)" : ""].")) - return - -/client/proc/admin_cancel_shuttle() - set category = "Admin.Events" - set name = "Cancel Shuttle" - if(!check_rights(0)) - return - if(tgui_alert(usr, "You sure?", "Confirm", list("Yes", "No")) != "Yes") - return - - if(SSshuttle.admin_emergency_no_recall) - SSshuttle.admin_emergency_no_recall = FALSE + log_admin("[key_name(user)] admin-called the emergency shuttle.") + message_admins(span_adminnotice("[key_name_admin(user)] admin-called the emergency shuttle[confirm == "Yes (No Recall)" ? " (non-recallable)" : ""].")) +ADMIN_VERB(cancel_shuttle, R_ADMIN, "Cancel Shuttle", "Recall the shuttle, regardless of circumstances.", ADMIN_CATEGORY_EVENTS) if(EMERGENCY_AT_LEAST_DOCKED) return + if(tgui_alert(user, "You sure?", "Confirm", list("Yes", "No")) != "Yes") + return + SSshuttle.admin_emergency_no_recall = FALSE SSshuttle.emergency.cancel() BLACKBOX_LOG_ADMIN_VERB("Cancel Shuttle") - log_admin("[key_name(usr)] admin-recalled the emergency shuttle.") - message_admins(span_adminnotice("[key_name_admin(usr)] admin-recalled the emergency shuttle.")) - - return - -/client/proc/admin_disable_shuttle() - set category = "Admin.Events" - set name = "Disable Shuttle" - - if(!check_rights(R_ADMIN)) - return + log_admin("[key_name(user)] admin-recalled the emergency shuttle.") + message_admins(span_adminnotice("[key_name_admin(user)] admin-recalled the emergency shuttle.")) +ADMIN_VERB(disable_shuttle, R_ADMIN, "Disable Shuttle", "Those fuckers aren't getting out.", ADMIN_CATEGORY_EVENTS) if(SSshuttle.emergency.mode == SHUTTLE_DISABLED) - to_chat(usr, span_warning("Error, shuttle is already disabled.")) + to_chat(user, span_warning("Error, shuttle is already disabled.")) return - if(tgui_alert(usr, "You sure?", "Confirm", list("Yes", "No")) != "Yes") + if(tgui_alert(user, "You sure?", "Confirm", list("Yes", "No")) != "Yes") return - message_admins(span_adminnotice("[key_name_admin(usr)] disabled the shuttle.")) + message_admins(span_adminnotice("[key_name_admin(user)] disabled the shuttle.")) SSshuttle.last_mode = SSshuttle.emergency.mode SSshuttle.last_call_time = SSshuttle.emergency.timeLeft(1) @@ -232,21 +165,15 @@ color_override = "grey", ) -/client/proc/admin_enable_shuttle() - set category = "Admin.Events" - set name = "Enable Shuttle" - - if(!check_rights(R_ADMIN)) - return - +ADMIN_VERB(enable_shuttle, R_ADMIN, "Enable Shuttle", "Those fuckers ARE getting out.", ADMIN_CATEGORY_EVENTS) if(SSshuttle.emergency.mode != SHUTTLE_DISABLED) - to_chat(usr, span_warning("Error, shuttle not disabled.")) + to_chat(user, span_warning("Error, shuttle not disabled.")) return - if(tgui_alert(usr, "You sure?", "Confirm", list("Yes", "No")) != "Yes") + if(tgui_alert(user, "You sure?", "Confirm", list("Yes", "No")) != "Yes") return - message_admins(span_adminnotice("[key_name_admin(usr)] enabled the emergency shuttle.")) + message_admins(span_adminnotice("[key_name_admin(user)] enabled the emergency shuttle.")) SSshuttle.admin_emergency_no_recall = FALSE SSshuttle.emergency_no_recall = FALSE if(SSshuttle.last_mode == SHUTTLE_DISABLED) //If everything goes to shit, fix it. @@ -264,136 +191,77 @@ color_override = "green", ) -/client/proc/admin_hostile_environment() - set category = "Admin.Events" - set name = "Hostile Environment" - - if(!check_rights(R_ADMIN)) - return - - switch(tgui_alert(usr, "Select an Option", "Hostile Environment Manager", list("Enable", "Disable", "Clear All"))) +ADMIN_VERB(hostile_environment, R_ADMIN, "Hostile Environment", "Disable the shuttle, naturally.", ADMIN_CATEGORY_EVENTS) + switch(tgui_alert(user, "Select an Option", "Hostile Environment Manager", list("Enable", "Disable", "Clear All"))) if("Enable") if (SSshuttle.hostile_environments["Admin"] == TRUE) - to_chat(usr, span_warning("Error, admin hostile environment already enabled.")) + to_chat(user, span_warning("Error, admin hostile environment already enabled.")) else - message_admins(span_adminnotice("[key_name_admin(usr)] Enabled an admin hostile environment")) + message_admins(span_adminnotice("[key_name_admin(user)] Enabled an admin hostile environment")) SSshuttle.registerHostileEnvironment("Admin") if("Disable") if (!SSshuttle.hostile_environments["Admin"]) - to_chat(usr, span_warning("Error, no admin hostile environment found.")) + to_chat(user, span_warning("Error, no admin hostile environment found.")) else - message_admins(span_adminnotice("[key_name_admin(usr)] Disabled the admin hostile environment")) + message_admins(span_adminnotice("[key_name_admin(user)] Disabled the admin hostile environment")) SSshuttle.clearHostileEnvironment("Admin") if("Clear All") - message_admins(span_adminnotice("[key_name_admin(usr)] Disabled all current hostile environment sources")) + message_admins(span_adminnotice("[key_name_admin(user)] Disabled all current hostile environment sources")) SSshuttle.hostile_environments.Cut() SSshuttle.checkHostileEnvironment() -/client/proc/toggle_nuke(obj/machinery/nuclearbomb/N in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/nuclearbomb)) - set category = "Admin.Events" - set name = "Toggle Nuke" - set popup_menu = FALSE - if(!check_rights(R_DEBUG)) - return - - if(!N.timing) - var/newtime = input(usr, "Set activation timer.", "Activate Nuke", "[N.timer_set]") as num|null +ADMIN_VERB(toggle_nuke, R_DEBUG|R_ADMIN, "Toggle Nuke", "Arm or disarm a nuke.", ADMIN_CATEGORY_EVENTS, obj/machinery/nuclearbomb/nuke in world) + if(!nuke.timing) + var/newtime = input(user, "Set activation timer.", "Activate Nuke", "[nuke.timer_set]") as num|null if(!newtime) return - N.timer_set = newtime - N.toggle_nuke_safety() - N.toggle_nuke_armed() + nuke.timer_set = newtime + nuke.toggle_nuke_safety() + nuke.toggle_nuke_armed() - log_admin("[key_name(usr)] [N.timing ? "activated" : "deactivated"] a nuke at [AREACOORD(N)].") - message_admins("[ADMIN_LOOKUPFLW(usr)] [N.timing ? "activated" : "deactivated"] a nuke at [ADMIN_VERBOSEJMP(N)].") - SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Nuke", "[N.timing]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! + log_admin("[key_name(user)] [nuke.timing ? "activated" : "deactivated"] a nuke at [AREACOORD(nuke)].") + message_admins("[ADMIN_LOOKUPFLW(user)] [nuke.timing ? "activated" : "deactivated"] a nuke at [ADMIN_VERBOSEJMP(nuke)].") + SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Nuke", "[nuke.timing]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! -/client/proc/admin_change_sec_level() - set category = "Admin.Events" - set name = "Set Security Level" - set desc = "Changes the security level. Announcement only, i.e. setting to Delta won't activate nuke" - - if(!check_rights(R_ADMIN)) - return - - var/level = tgui_input_list(usr, "Select Security Level:", "Set Security Level", SSsecurity_level.available_levels) +ADMIN_VERB(change_sec_level, R_ADMIN, "Set Security Level", "Changes the security level. Announcement effects only.", ADMIN_CATEGORY_EVENTS) + var/level = tgui_input_list(user, "Select Security Level:", "Set Security Level", SSsecurity_level.available_levels) if(!level) return SSsecurity_level.set_level(level) - log_admin("[key_name(usr)] changed the security level to [level]") - message_admins("[key_name_admin(usr)] changed the security level to [level]") + log_admin("[key_name(user)] changed the security level to [level]") + message_admins("[key_name_admin(user)] changed the security level to [level]") BLACKBOX_LOG_ADMIN_VERB("Set Security Level [capitalize(level)]") -/client/proc/run_weather() - set category = "Admin.Events" - set name = "Run Weather" - set desc = "Triggers a weather on the z-level you choose." - - if(!holder) - return - - var/weather_type = input("Choose a weather", "Weather") as null|anything in sort_list(subtypesof(/datum/weather), GLOBAL_PROC_REF(cmp_typepaths_asc)) +ADMIN_VERB(run_weather, R_FUN, "Run Weather", "Triggers specific weather on the z-level you choose.", ADMIN_CATEGORY_EVENTS) + var/weather_type = input(user, "Choose a weather", "Weather") as null|anything in sort_list(subtypesof(/datum/weather), GLOBAL_PROC_REF(cmp_typepaths_asc)) if(!weather_type) return - var/turf/T = get_turf(mob) - var/z_level = input("Z-Level to target?", "Z-Level", T?.z) as num|null + var/turf/T = get_turf(user.mob) + var/z_level = input(user, "Z-Level to target?", "Z-Level", T?.z) as num|null if(!isnum(z_level)) return SSweather.run_weather(weather_type, z_level) - message_admins("[key_name_admin(usr)] started weather of type [weather_type] on the z-level [z_level].") - log_admin("[key_name(usr)] started weather of type [weather_type] on the z-level [z_level].") + message_admins("[key_name_admin(user)] started weather of type [weather_type] on the z-level [z_level].") + log_admin("[key_name(user)] started weather of type [weather_type] on the z-level [z_level].") BLACKBOX_LOG_ADMIN_VERB("Run Weather") -/client/proc/add_marked_mob_ability() - set category = "Admin.Events" - set name = "Add Mob Ability (Marked Mob)" - set desc = "Adds an ability to a marked mob." - - if(!holder) - return - - if(!isliving(holder.marked_datum)) - to_chat(usr, span_warning("Error: Please mark a mob to add actions to it.")) - return - give_mob_action(holder.marked_datum) - -/client/proc/remove_marked_mob_ability() - set category = "Admin.Events" - set name = "Remove Mob Ability (Marked Mob)" - set desc = "Removes an ability from marked mob." - - if(!holder) - return - - if(!isliving(holder.marked_datum)) - to_chat(usr, span_warning("Error: Please mark a mob to remove actions from it.")) - return - remove_mob_action(holder.marked_datum) - - -/client/proc/command_report_footnote() - set category = "Admin.Events" - set name = "Command Report Footnote" - set desc = "Adds a footnote to the roundstart command report." - - if(!check_rights(R_ADMIN)) - return - +ADMIN_VERB(command_report_footnote, R_ADMIN, "Command Report Footnote", "Adds a footnote to the roundstart command report.", ADMIN_CATEGORY_EVENTS) var/datum/command_footnote/command_report_footnote = new /datum/command_footnote() - SScommunications.block_command_report++ //Add a blocking condition to the counter until the inputs are done. - - command_report_footnote.message = tgui_input_text(usr, "This message will be attached to the bottom of the roundstart threat report. Be sure to delay the roundstart report if you need extra time.", "P.S.") + SScommunications.block_command_report += 1 //Add a blocking condition to the counter until the inputs are done. + command_report_footnote.message = tgui_input_text(user, "This message will be attached to the bottom of the roundstart threat report. Be sure to delay the roundstart report if you need extra time.", "P.S.") if(!command_report_footnote.message) + SScommunications.block_command_report -= 1 + qdel(command_report_footnote) return - command_report_footnote.signature = tgui_input_text(usr, "Whose signature will appear on this footnote?", "Also sign here, here, aaand here.") + command_report_footnote.signature = tgui_input_text(user, "Whose signature will appear on this footnote?", "Also sign here, here, aaand here.") if(!command_report_footnote.signature) command_report_footnote.signature = "Classified" @@ -401,24 +269,12 @@ SScommunications.command_report_footnotes += command_report_footnote SScommunications.block_command_report-- - message_admins("[usr] has added a footnote to the command report: [command_report_footnote.message], signed [command_report_footnote.signature]") + message_admins("[user] has added a footnote to the command report: [command_report_footnote.message], signed [command_report_footnote.signature]") /datum/command_footnote var/message var/signature -/client/proc/delay_command_report() - set category = "Admin.Events" - set name = "Delay Command Report" - set desc = "Prevents the roundstart command report from being sent until toggled." - - if(!check_rights(R_ADMIN)) - return - - if(SScommunications.block_command_report) //If it's anything other than 0, decrease. If 0, increase. - SScommunications.block_command_report-- - message_admins("[usr] has enabled the roundstart command report.") - else - SScommunications.block_command_report++ - message_admins("[usr] has delayed the roundstart command report.") - +ADMIN_VERB(delay_command_report, R_FUN, "Delay Command Report", "Prevents the roundstart command report from being sent; or forces it to send it delayed.", ADMIN_CATEGORY_EVENTS) + SScommunications.block_command_report = !SScommunications.block_command_report + message_admins("[key_name_admin(user)] has [(SScommunications.block_command_report ? "delayed" : "sent")] the roundstart command report.") diff --git a/code/modules/admin/verbs/adminfun.dm b/code/modules/admin/verbs/adminfun.dm index fcba8d40928..8bc7a611b35 100644 --- a/code/modules/admin/verbs/adminfun.dm +++ b/code/modules/admin/verbs/adminfun.dm @@ -1,74 +1,54 @@ -// Admin Tab - Fun Verbs - -/client/proc/cmd_admin_explosion(atom/O as obj|mob|turf in world) - set category = "Admin.Fun" - set name = "Explosion" - - if(!check_rights(R_ADMIN)) - return - - var/devastation = input("Range of total devastation. -1 to none", "Input") as num|null +ADMIN_VERB(admin_explosion, R_ADMIN|R_FUN, "Explosion", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, atom/orignator as obj|mob|turf) + var/devastation = input(user, "Range of total devastation. -1 to none", "Input") as num|null if(devastation == null) return - var/heavy = input("Range of heavy impact. -1 to none", "Input") as num|null + var/heavy = input(user, "Range of heavy impact. -1 to none", "Input") as num|null if(heavy == null) return - var/light = input("Range of light impact. -1 to none", "Input") as num|null + var/light = input(user, "Range of light impact. -1 to none", "Input") as num|null if(light == null) return - var/flash = input("Range of flash. -1 to none", "Input") as num|null + var/flash = input(user, "Range of flash. -1 to none", "Input") as num|null if(flash == null) return - var/flames = input("Range of flames. -1 to none", "Input") as num|null + var/flames = input(user, "Range of flames. -1 to none", "Input") as num|null if(flames == null) return if ((devastation != -1) || (heavy != -1) || (light != -1) || (flash != -1) || (flames != -1)) if ((devastation > 20) || (heavy > 20) || (light > 20) || (flames > 20)) - if (tgui_alert(usr, "Are you sure you want to do this? It will laaag.", "Confirmation", list("Yes", "No")) == "No") + if (tgui_alert(user, "Are you sure you want to do this? It will laaag.", "Confirmation", list("Yes", "No")) == "No") return - explosion(O, devastation, heavy, light, flames, flash, explosion_cause = mob) - log_admin("[key_name(usr)] created an explosion ([devastation],[heavy],[light],[flames]) at [AREACOORD(O)]") - message_admins("[key_name_admin(usr)] created an explosion ([devastation],[heavy],[light],[flames]) at [AREACOORD(O)]") + explosion(orignator, devastation, heavy, light, flames, flash, explosion_cause = user.mob) + log_admin("[key_name(user)] created an explosion ([devastation],[heavy],[light],[flames]) at [AREACOORD(orignator)]") + message_admins("[key_name_admin(user)] created an explosion ([devastation],[heavy],[light],[flames]) at [AREACOORD(orignator)]") BLACKBOX_LOG_ADMIN_VERB("Explosion") -/client/proc/cmd_admin_emp(atom/O as obj|mob|turf in world) - set category = "Admin.Fun" - set name = "EM Pulse" - - if(!check_rights(R_ADMIN)) - return - - var/heavy = input("Range of heavy pulse.", "Input") as num|null +ADMIN_VERB(admin_emp, R_ADMIN|R_FUN, "EM Pulse", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, atom/orignator as obj|mob|turf) + var/heavy = input(user, "Range of heavy pulse.", "Input") as num|null if(heavy == null) return - var/light = input("Range of light pulse.", "Input") as num|null + var/light = input(user, "Range of light pulse.", "Input") as num|null if(light == null) return if (heavy || light) - empulse(O, heavy, light) - log_admin("[key_name(usr)] created an EM Pulse ([heavy],[light]) at [AREACOORD(O)]") - message_admins("[key_name_admin(usr)] created an EM Pulse ([heavy],[light]) at [AREACOORD(O)]") + empulse(orignator, heavy, light) + log_admin("[key_name(user)] created an EM Pulse ([heavy],[light]) at [AREACOORD(orignator)]") + message_admins("[key_name_admin(user)] created an EM Pulse ([heavy],[light]) at [AREACOORD(orignator)]") BLACKBOX_LOG_ADMIN_VERB("EM Pulse") -/client/proc/cmd_admin_gib(mob/victim in GLOB.mob_list) - set category = "Admin.Fun" - set name = "Gib" - - if(!check_rights(R_ADMIN)) - return - - var/confirm = tgui_alert(usr, "Drop a brain?", "Confirm", list("Yes", "No","Cancel")) || "Cancel" +ADMIN_VERB(gib_them, R_ADMIN, "Gib", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/victim in GLOB.mob_list) + var/confirm = tgui_alert(user, "Drop a brain?", "Confirm", list("Yes", "No","Cancel")) || "Cancel" if(confirm == "Cancel") return //Due to the delay here its easy for something to have happened to the mob if(isnull(victim)) return - log_admin("[key_name(usr)] has gibbed [key_name(victim)]") - message_admins("[key_name_admin(usr)] has gibbed [key_name_admin(victim)]") + log_admin("[key_name(user)] has gibbed [key_name(victim)]") + message_admins("[key_name_admin(user)] has gibbed [key_name_admin(victim)]") if(isobserver(victim)) new /obj/effect/gibspawner/generic(get_turf(victim)) @@ -84,62 +64,47 @@ BLACKBOX_LOG_ADMIN_VERB("Gib") -/client/proc/cmd_admin_gib_self() - set name = "Gibself" - set category = "Admin.Fun" - - var/confirm = tgui_alert(usr, "You sure?", "Confirm", list("Yes", "No")) +ADMIN_VERB(gib_self, R_ADMIN, "Gibself", "Give yourself the same treatment you give others.", ADMIN_CATEGORY_FUN) + var/confirm = tgui_alert(user, "You sure?", "Confirm", list("Yes", "No")) if(confirm != "Yes") return - log_admin("[key_name(usr)] used gibself.") - message_admins(span_adminnotice("[key_name_admin(usr)] used gibself.")) + log_admin("[key_name(user)] used gibself.") + message_admins(span_adminnotice("[key_name_admin(user)] used gibself.")) BLACKBOX_LOG_ADMIN_VERB("Gib Self") - var/mob/living/ourself = mob + var/mob/living/ourself = user.mob if (istype(ourself)) ourself.gib() -/client/proc/everyone_random() - set category = "Admin.Fun" - set name = "Make Everyone Random" - set desc = "Make everyone have a random appearance. You can only use this before rounds!" - +ADMIN_VERB(everyone_random, R_SERVER, "Make Everyone Random", "Make everyone have a random appearance.", ADMIN_CATEGORY_FUN) if(SSticker.HasRoundStarted()) - to_chat(usr, "Nope you can't do this, the game's already started. This only works before rounds!", confidential = TRUE) + to_chat(user, "Nope you can't do this, the game's already started. This only works before rounds!", confidential = TRUE) return var/frn = CONFIG_GET(flag/force_random_names) if(frn) CONFIG_SET(flag/force_random_names, FALSE) - message_admins("Admin [key_name_admin(usr)] has disabled \"Everyone is Special\" mode.") - to_chat(usr, "Disabled.", confidential = TRUE) + message_admins("Admin [key_name_admin(user)] has disabled \"Everyone is Special\" mode.") + to_chat(user, "Disabled.", confidential = TRUE) return - var/notifyplayers = tgui_alert(usr, "Do you want to notify the players?", "Options", list("Yes", "No", "Cancel")) || "Cancel" + var/notifyplayers = tgui_alert(user, "Do you want to notify the players?", "Options", list("Yes", "No", "Cancel")) || "Cancel" if(notifyplayers == "Cancel") return - log_admin("Admin [key_name(src)] has forced the players to have random appearances.") - message_admins("Admin [key_name_admin(usr)] has forced the players to have random appearances.") + log_admin("Admin [key_name(user)] has forced the players to have random appearances.") + message_admins("Admin [key_name_admin(user)] has forced the players to have random appearances.") if(notifyplayers == "Yes") - to_chat(world, span_adminnotice("Admin [usr.key] has forced the players to have completely random identities!"), confidential = TRUE) + to_chat(world, span_adminnotice("Admin [user.key] has forced the players to have completely random identities!"), confidential = TRUE) - to_chat(usr, "Remember: you can always disable the randomness by using the verb again, assuming the round hasn't started yet.", confidential = TRUE) + to_chat(user, "Remember: you can always disable the randomness by using the verb again, assuming the round hasn't started yet.", confidential = TRUE) CONFIG_SET(flag/force_random_names, TRUE) BLACKBOX_LOG_ADMIN_VERB("Make Everyone Random") -/client/proc/mass_zombie_infection() - set category = "Admin.Fun" - set name = "Mass Zombie Infection" - set desc = "Infects all humans with a latent organ that will zombify \ - them on death." - - if(!check_rights(R_ADMIN)) - return - - var/confirm = tgui_alert(usr, "Please confirm you want to add latent zombie organs in all humans?", "Confirm Zombies", list("Yes", "No")) +ADMIN_VERB(mass_zombie_infection, R_ADMIN, "Mass Zombie Infection", "Infects all humans with a latent organ that will zombify them on death.", ADMIN_CATEGORY_FUN) + var/confirm = tgui_alert(user, "Please confirm you want to add latent zombie organs in all humans?", "Confirm Zombies", list("Yes", "No")) if(confirm != "Yes") return @@ -147,45 +112,32 @@ var/mob/living/carbon/human/H = i new /obj/item/organ/internal/zombie_infection/nodamage(H) - message_admins("[key_name_admin(usr)] added a latent zombie infection to all humans.") - log_admin("[key_name(usr)] added a latent zombie infection to all humans.") + message_admins("[key_name_admin(user)] added a latent zombie infection to all humans.") + log_admin("[key_name(user)] added a latent zombie infection to all humans.") BLACKBOX_LOG_ADMIN_VERB("Mass Zombie Infection") -/client/proc/mass_zombie_cure() - set category = "Admin.Fun" - set name = "Mass Zombie Cure" - set desc = "Removes the zombie infection from all humans, returning them to normal." - if(!check_rights(R_ADMIN)) - return - - var/confirm = tgui_alert(usr, "Please confirm you want to cure all zombies?", "Confirm Zombie Cure", list("Yes", "No")) +ADMIN_VERB(mass_zombie_cure, R_ADMIN, "Mass Zombie Cure", "Removes the zombie infection from all humans, returning them to normal.", ADMIN_CATEGORY_FUN) + var/confirm = tgui_alert(user, "Please confirm you want to cure all zombies?", "Confirm Zombie Cure", list("Yes", "No")) if(confirm != "Yes") return for(var/obj/item/organ/internal/zombie_infection/nodamage/I in GLOB.zombie_infection_list) qdel(I) - message_admins("[key_name_admin(usr)] cured all zombies.") - log_admin("[key_name(usr)] cured all zombies.") + message_admins("[key_name_admin(user)] cured all zombies.") + log_admin("[key_name(user)] cured all zombies.") BLACKBOX_LOG_ADMIN_VERB("Mass Zombie Cure") -/client/proc/polymorph_all() - set category = "Admin.Fun" - set name = "Polymorph All" - set desc = "Applies the effects of the bolt of change to every single mob." - - if(!check_rights(R_ADMIN)) - return - - var/confirm = tgui_alert(usr, "Please confirm you want polymorph all mobs?", "Confirm Polymorph", list("Yes", "No")) +ADMIN_VERB(polymorph_all, R_ADMIN, "Polymorph All", "Applies the effects of the bolt of change to every single mob.", ADMIN_CATEGORY_FUN) + var/confirm = tgui_alert(user, "Please confirm you want polymorph all mobs?", "Confirm Polymorph", list("Yes", "No")) if(confirm != "Yes") return var/list/mobs = shuffle(GLOB.alive_mob_list.Copy()) // might change while iterating - var/who_did_it = key_name_admin(usr) + var/who_did_it = key_name_admin(user) - message_admins("[key_name_admin(usr)] started polymorphed all living mobs.") - log_admin("[key_name(usr)] polymorphed all living mobs.") + message_admins("[key_name_admin(user)] started polymorphed all living mobs.") + log_admin("[key_name(user)] polymorphed all living mobs.") BLACKBOX_LOG_ADMIN_VERB("Polymorph All") for(var/mob/living/M in mobs) @@ -201,23 +153,18 @@ message_admins("Mass polymorph started by [who_did_it] is complete.") -/client/proc/smite(mob/living/target as mob) - set category = "Admin.Fun" - set name = "Smite" - if(!check_rights(R_ADMIN) || !check_rights(R_FUN)) - return - - var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in GLOB.smites +ADMIN_VERB_AND_CONTEXT_MENU(admin_smite, R_ADMIN|R_FUN, "Smite", "Smite a player with divine power.", ADMIN_CATEGORY_FUN, mob/living/target in world) + var/punishment = input(user, "Choose a punishment", "DIVINE SMITING") as null|anything in GLOB.smites if(QDELETED(target) || !punishment) return var/smite_path = GLOB.smites[punishment] var/datum/smite/smite = new smite_path - var/configuration_success = smite.configure(usr) + var/configuration_success = smite.configure(user) if (configuration_success == FALSE) return - smite.effect(src, target) + smite.effect(user, target) /// "Turns" people into objects. Really, we just add them to the contents of the item. /proc/objectify(atom/movable/target, path) diff --git a/code/modules/admin/verbs/admingame.dm b/code/modules/admin/verbs/admingame.dm index b43cc2f5788..e525a6d0627 100644 --- a/code/modules/admin/verbs/admingame.dm +++ b/code/modules/admin/verbs/admingame.dm @@ -1,183 +1,176 @@ -// Admin Tab - Game Verbs +ADMIN_VERB(cmd_player_panel, R_ADMIN, "Player Panel", "See all players and their Player Panel.", ADMIN_CATEGORY_GAME) + user.holder.player_panel_new() -/datum/admins/proc/show_player_panel(mob/M in GLOB.mob_list) - set category = "Admin.Game" - set name = "Show Player Panel" - set desc="Edit player (respawn, ban, heal, etc)" +ADMIN_VERB_ONLY_CONTEXT_MENU(show_player_panel, R_ADMIN, "Show Player Panel", mob/player in world) + log_admin("[key_name(user)] checked the individual player panel for [key_name(player)][isobserver(user.mob)?"":" while in game"].") - if(!check_rights()) + if(!player) + to_chat(user, span_warning("You seem to be selecting a mob that doesn't exist anymore."), confidential = TRUE) return - log_admin("[key_name(usr)] checked the individual player panel for [key_name(M)][isobserver(usr)?"":" while in game"].") - - if(!M) - to_chat(usr, span_warning("You seem to be selecting a mob that doesn't exist anymore."), confidential = TRUE) - return - - var/body = "Options for [M.key]" - body += "Options panel for [M]" - if(M.client) - body += " played by [M.client] " - body += "\[[M.client.holder ? M.client.holder.rank_names() : "Player"]\]" + var/body = "Options for [player.key]" + body += "Options panel for [player]" + if(player.client) + body += " played by [player.client] " + body += "\[[player.client.holder ? player.client.holder.rank_names() : "Player"]\]" if(CONFIG_GET(flag/use_exp_tracking)) - body += "\[" + M.client.get_exp_living(FALSE) + "\]" + body += "\[" + player.client.get_exp_living(FALSE) + "\]" // BUBBERS EDIT START - Job exemption - body += "
    \[Job Exemption Menu\]" + body += "
    \[Job Exemption Menu\]" // BUBBERS EDIT END - - if(isnewplayer(M)) + if(isnewplayer(player)) body += " Hasn't Entered Game " else - body += " \[Heal\] " + body += " \[Heal\] " - if(M.ckey) - body += "
    \[Find Updated Panel\]" + if(player.ckey) + body += "
    \[Find Updated Panel\]" - if(M.client) - body += "
    \[First Seen: [M.client.player_join_date]\]\[Byond account registered on: [M.client.account_join_date]\]" + if(player.client) + body += "
    \[First Seen: [player.client.player_join_date]\]\[Byond account registered on: [player.client.account_join_date]\]" // SKYRAT EDIT ADDITION START - Player Ranks var/list/player_ranks = list() - if(SSplayer_ranks.is_donator(M.client, admin_bypass = FALSE)) + if(SSplayer_ranks.is_donator(player.client, admin_bypass = FALSE)) player_ranks += "Donator" - if(SSplayer_ranks.is_mentor(M.client, admin_bypass = FALSE)) + if(SSplayer_ranks.is_mentor(player.client, admin_bypass = FALSE)) player_ranks += "Mentor" - if(SSplayer_ranks.is_veteran(M.client, admin_bypass = FALSE)) + if(SSplayer_ranks.is_veteran(player.client, admin_bypass = FALSE)) player_ranks += "Veteran" //BUBBER ADDITION START - if(SSplayer_ranks.is_vetted(M.client, admin_bypass = FALSE)) + if(SSplayer_ranks.is_vetted(player.client, admin_bypass = FALSE)) player_ranks |= "Vetted" // BUBBER ADDITION END body += "

    Player Ranks: [length(player_ranks) ? player_ranks.Join(", ") : "None"]" // SKYRAT EDIT END body += "

    CentCom Galactic Ban DB: " if(CONFIG_GET(string/centcom_ban_db)) - body += "Search" + body += "Search" else body += "Disabled" body += "

    Show related accounts by: " - body += "\[ CID | " - body += "IP \]" + body += "\[ CID | " + body += "IP \]" var/full_version = "Unknown" - if(M.client.byond_version) - full_version = "[M.client.byond_version].[M.client.byond_build ? M.client.byond_build : "xxx"]" + if(player.client.byond_version) + full_version = "[player.client.byond_version].[player.client.byond_build ? player.client.byond_build : "xxx"]" body += "
    \[Byond version: [full_version]\]
    " body += "

    \[ " - body += "VV - " - if(M.mind) - body += "TP - " - body += "SKILLS - " + body += "VV - " + if(player.mind) + body += "TP - " + body += "SKILLS - " else - body += "Init Mind - " - if (iscyborg(M)) - body += "BP - " - body += "PM - " - body += "SM - " - if (ishuman(M) && M.mind) - body += "HM - " - body += "FLW - " + body += "Init Mind - " + if (iscyborg(player)) + body += "BP - " + body += "PM - " + body += "SM - " + if (ishuman(player) && player.mind) + body += "HM - " + body += "FLW - " //Default to client logs if available var/source = LOGSRC_MOB - if(M.ckey) + if(player.ckey) source = LOGSRC_CKEY - body += "LOGS\]
    " + body += "LOGS\]
    " - body += "Mob type = [M.type]

    " + body += "Mob type = [player.type]

    " - if(M.client) + if(player.client) body += "Old names: " - var/datum/player_details/deets = GLOB.player_details[M.ckey] + var/datum/player_details/deets = GLOB.player_details[player.ckey] if(deets) body += deets.get_played_names() else body += "None?!" body += "

    " - body += "Kick | " - if(M.client) - body += "Ban | " + body += "Kick | " + if(player.client) + body += "Ban | " else - body += "Ban | " + body += "Ban | " - body += "Notes | Messages | Watchlist | " - if(M.client) - body += "| Prison | " - body += "\ Send back to Lobby | " - var/muted = M.client.prefs.muted + body += "Notes | Messages | Watchlist | " + if(player.client) + body += "| Prison | " + body += "\ Send back to Lobby | " + var/muted = player.client.prefs.muted body += "
    Mute: " - body += "\[IC | " - body += "OOC | " - body += "PRAY | " - body += "ADMINHELP | " + body += "\[IC | " + body += "OOC | " + body += "PRAY | " + body += "ADMINHELP | " //Skyrat Addition Begin - LOOC muting again. - body += "DEADCHAT | " - body += "LOOC\]" + body += "DEADCHAT | " + body += "LOOC\]" //Skyrat Addition End - LOOC muting again. - body += " WEBREQ | " - body += "DEADCHAT\]" - body += "(toggle all)" + body += "WEBREQ | " + body += "DEADCHAT\]" + body += "(toggle all)" body += "

    " - body += "Jump to | " - body += "Get | " - body += "Send To" + body += "Jump to | " + body += "Get | " + body += "Send To" body += "

    " - body += "Traitor panel | " - body += "Narrate to | " - body += "Subtle message | " - body += "Play sound to | " - body += "Language Menu" + body += "Traitor panel | " + body += "Narrate to | " + body += "Subtle message | " + body += "Play sound to | " + body += "Language Menu" - if(M.client) - if(!isnewplayer(M)) + if(player.client) + if(!isnewplayer(player)) body += "

    " body += "Transformation:
    " - if(isobserver(M)) + if(isobserver(player)) body += "Ghost | " else - body += "Make Ghost | " + body += "Make Ghost | " - if(ishuman(M) && !ismonkey(M)) + if(ishuman(player) && !ismonkey(player)) body += "Human | " else - body += "Make Human | " + body += "Make Human | " - if(ismonkey(M)) + if(ismonkey(player)) body += "Monkey | " else - body += "Make Monkey | " + body += "Make Monkey | " - if(iscyborg(M)) + if(iscyborg(player)) body += "Cyborg | " else - body += "Make Cyborg | " + body += "Make Cyborg | " - if(isAI(M)) + if(isAI(player)) body += "AI" else - body += "Make AI" + body += "Make AI" body += "

    " body += "Other actions:" body += "
    " - if(!isnewplayer(M)) - body += "Forcesay | " - body += "Apply Client Quirks | " - body += "Thunderdome 1 | " - body += "Thunderdome 2 | " - body += "Thunderdome Admin | " - body += "Thunderdome Observer | " - body += "Commend Behavior | " + if(!isnewplayer(player)) + body += "Forcesay | " + body += "Apply Client Quirks | " + body += "Thunderdome 1 | " + body += "Thunderdome 2 | " + body += "Thunderdome Admin | " + body += "Thunderdome Observer | " + body += "Commend Behavior | " body += "
    " body += "" - usr << browse(body, "window=adminplayeropts-[REF(M)];size=550x515") + user << browse(body, "window=adminplayeropts-[REF(player)];size=550x515") BLACKBOX_LOG_ADMIN_VERB("Player Panel") /client/proc/cmd_admin_godmode(mob/M in GLOB.mob_list) @@ -200,14 +193,8 @@ If a guy was gibbed and you want to revive him, this is a good way to do so. Works kind of like entering the game with a new character. Character receives a new mind if they didn't have one. Traitors and the like can also be revived with the previous role mostly intact. /N */ -/client/proc/respawn_character() - set category = "Admin.Game" - set name = "Respawn Character" - set desc = "Respawn a person that has been gibbed/dusted/killed. They must be a ghost for this to work and preferably should not have a body to go back into." - if(!check_rights(R_ADMIN)) - return - - var/input = ckey(input(src, "Please specify which key will be respawned.", "Key", "")) +ADMIN_VERB(respawn_character, R_ADMIN, "Respawn Character", "Respawn a player that has been round removed in some manner. They must be a ghost.", ADMIN_CATEGORY_GAME) + var/input = ckey(input(user, "Please specify which key will be respawned.", "Key", "")) if(!input) return @@ -218,19 +205,19 @@ Traitors and the like can also be revived with the previous role mostly intact. break if(!G_found)//If a ghost was not found. - to_chat(usr, "There is no active key like that in the game or the person is not currently a ghost.", confidential = TRUE) + to_chat(user, "There is no active key like that in the game or the person is not currently a ghost.", confidential = TRUE) return if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something //check if they were a monkey if(findtext(G_found.real_name,"monkey")) - if(tgui_alert(usr,"This character appears to have been a monkey. Would you like to respawn them as such?",,list("Yes","No")) == "Yes") + if(tgui_alert(user,"This character appears to have been a monkey. Would you like to respawn them as such?",,list("Yes","No")) == "Yes") var/mob/living/carbon/human/species/monkey/new_monkey = new SSjob.SendToLateJoin(new_monkey) G_found.mind.transfer_to(new_monkey) //be careful when doing stuff like this! I've already checked the mind isn't in use new_monkey.key = G_found.key to_chat(new_monkey, "You have been fully respawned. Enjoy the game.", confidential = TRUE) - var/msg = span_adminnotice("[key_name_admin(usr)] has respawned [new_monkey.key] as a filthy monkey.") + var/msg = span_adminnotice("[key_name_admin(user)] has respawned [new_monkey.key] as a filthy monkey.") message_admins(msg) admin_ticket_log(new_monkey, msg) return //all done. The ghost is auto-deleted @@ -246,7 +233,7 @@ Traitors and the like can also be revived with the previous role mostly intact. if(record_found)//If they have a record we can determine a few things. new_character.real_name = record_found.name - new_character.gender = lowertext(record_found.gender) + new_character.gender = LOWER_TEXT(record_found.gender) new_character.age = record_found.age var/datum/dna/found_dna = record_found.locked_dna new_character.hardset_dna(found_dna.unique_identity, found_dna.mutation_index, null, record_found.name, record_found.blood_type, new record_found.species_type, found_dna.features) @@ -272,7 +259,7 @@ Traitors and the like can also be revived with the previous role mostly intact. */ //Two variables to properly announce later on. - var/admin = key_name_admin(src) + var/admin = key_name_admin(user) var/player_key = G_found.key //Now for special roles and equipment. @@ -327,13 +314,8 @@ Traitors and the like can also be revived with the previous role mostly intact. BLACKBOX_LOG_ADMIN_VERB("Respawn Character") return new_character -/client/proc/cmd_admin_list_open_jobs() - set category = "Admin.Game" - set name = "Manage Job Slots" - - if(!check_rights(R_ADMIN)) - return - holder.manage_free_slots() +ADMIN_VERB(manage_job_slots, R_ADMIN, "Manage Job Slots", "Manage the number of available job slots.", ADMIN_CATEGORY_GAME) + user.holder.manage_free_slots() BLACKBOX_LOG_ADMIN_VERB("Manage Job Slots") /datum/admins/proc/manage_free_slots() @@ -376,38 +358,25 @@ Traitors and the like can also be revived with the previous role mostly intact. browser.set_content(dat.Join()) browser.open() -/client/proc/toggle_view_range() - set category = "Admin.Game" - set name = "Change View Range" - set desc = "switches between 1x and custom views" - - if(view_size.getView() == view_size.default) - view_size.setTo(input("Select view range:", "FUCK YE", 7) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,37) - 7) +ADMIN_VERB(toggle_view_range, R_ADMIN, "Change View Range", "Switch between 1x and custom views.", ADMIN_CATEGORY_GAME) + if(user.view_size.getView() == user.view_size.default) + user.view_size.setTo(input(user, "Select view range:", "FUCK YE", 7) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,37) - 7) else - view_size.resetToDefault(getScreenSize(prefs.read_preference(/datum/preference/toggle/widescreen))) + user.view_size.resetToDefault(getScreenSize(user.prefs.read_preference(/datum/preference/toggle/widescreen))) - log_admin("[key_name(usr)] changed their view range to [view].") - //message_admins("\blue [key_name_admin(usr)] changed their view range to [view].") //why? removed by order of XSI + log_admin("[key_name(user)] changed their view range to [user.view].") + SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Change View Range", "[user.view]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! - SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Change View Range", "[view]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! - -/client/proc/toggle_combo_hud() - set category = "Admin.Game" - set name = "Toggle Combo HUD" - set desc = "Toggles the Admin Combo HUD (antag, sci, med, eng)" - - if(!check_rights(R_ADMIN)) - return - - if (combo_hud_enabled) - disable_combo_hud() +ADMIN_VERB(combo_hud, R_ADMIN, "Toggle Combo HUD", "Toggles the Admin Combo HUD.", ADMIN_CATEGORY_GAME) + if(user.combo_hud_enabled) + user.disable_combo_hud() else - enable_combo_hud() + user.enable_combo_hud() - to_chat(usr, "You toggled your admin combo HUD [combo_hud_enabled ? "ON" : "OFF"].", confidential = TRUE) - message_admins("[key_name_admin(usr)] toggled their admin combo HUD [combo_hud_enabled ? "ON" : "OFF"].") - log_admin("[key_name(usr)] toggled their admin combo HUD [combo_hud_enabled ? "ON" : "OFF"].") - SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Combo HUD", "[combo_hud_enabled ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! + to_chat(user, "You toggled your admin combo HUD [user.combo_hud_enabled ? "ON" : "OFF"].", confidential = TRUE) + message_admins("[key_name_admin(user)] toggled their admin combo HUD [user.combo_hud_enabled ? "ON" : "OFF"].") + log_admin("[key_name(user)] toggled their admin combo HUD [user.combo_hud_enabled ? "ON" : "OFF"].") + SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Combo HUD", "[user.combo_hud_enabled ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! /client/proc/enable_combo_hud() if (combo_hud_enabled) @@ -441,47 +410,31 @@ Traitors and the like can also be revived with the previous role mostly intact. mob.lighting_cutoff = mob.default_lighting_cutoff() mob.update_sight() -/datum/admins/proc/show_traitor_panel(mob/target_mob in GLOB.mob_list) - set category = "Admin.Game" - set desc = "Edit mobs's memory and role" - set name = "Show Traitor Panel" +ADMIN_VERB(show_traitor_panel, R_ADMIN, "Show Traitor Panel", "Edit mobs's memory and role", ADMIN_CATEGORY_GAME, mob/target_mob) var/datum/mind/target_mind = target_mob.mind if(!target_mind) - to_chat(usr, "This mob has no mind!", confidential = TRUE) + to_chat(user, "This mob has no mind!", confidential = TRUE) return if(!istype(target_mob) && !istype(target_mind)) - to_chat(usr, "This can only be used on instances of type /mob and /mind", confidential = TRUE) + to_chat(user, "This can only be used on instances of type /mob and /mind", confidential = TRUE) return target_mind.traitor_panel() BLACKBOX_LOG_ADMIN_VERB("Traitor Panel") -/datum/admins/proc/show_skill_panel(target) - set category = "Admin.Game" - set desc = "Edit mobs's experience and skill levels" - set name = "Show Skill Panel" +ADMIN_VERB(show_skill_panel, R_ADMIN, "Show Skill Panel", "Edit mobs's experience and skill levels", ADMIN_CATEGORY_GAME, mob/target_mob) var/datum/mind/target_mind - if(ismob(target)) - var/mob/target_mob = target - target_mind = target_mob.mind - else if (istype(target, /datum/mind)) - target_mind = target + if(istype(target_mob, /datum/mind)) + target_mind = target_mob else - to_chat(usr, "This can only be used on instances of type /mob and /mind", confidential = TRUE) - return - var/datum/skill_panel/SP = new(usr, target_mind) - SP.ui_interact(usr) + target_mind = target_mob.mind -/datum/admins/proc/show_lag_switch_panel() - set category = "Admin.Game" - set name = "Show Lag Switches" - set desc="Display the controls for drastic lag mitigation measures." + var/datum/skill_panel/SP = new(user, target_mind) + SP.ui_interact(user.mob) +ADMIN_VERB(lag_switch_panel, R_ADMIN, "Show Lag Switches", "Display the controls for drastic lag mitigation.", ADMIN_CATEGORY_GAME) if(!SSlag_switch.initialized) - to_chat(usr, span_notice("The Lag Switch subsystem has not yet been initialized.")) + to_chat(user, span_notice("The Lag Switch subsystem has not yet been initialized.")) return - if(!check_rights()) - return - var/list/dat = list("Lag Switches

    Lag (Reduction) Switches

    ") dat += "Automatic Trigger: [SSlag_switch.auto_switch ? "On" : "Off"]
    " dat += "Population Threshold: [SSlag_switch.trigger_pop]
    " @@ -500,4 +453,4 @@ Traitors and the like can also be revived with the previous role mostly intact. dat += "Disable footsteps: [SSlag_switch.measures[DISABLE_FOOTSTEPS] ? "On" : "Off"] - trait applies to character
    " dat += "Disable character creator: [SSlag_switch.measures[DISABLE_CREATOR] ? "On" : "Off"] - trait applies to all
    " // SKRYAT EDIT ADDITION dat += "" - usr << browse(dat.Join(), "window=lag_switch_panel;size=420x480") + user << browse(dat.Join(), "window=lag_switch_panel;size=420x480") diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index bd2f6310bd5..e759f737e51 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -1107,10 +1107,10 @@ GLOBAL_DATUM_INIT(admin_help_ui_handler, /datum/admin_help_ui_handler, new) if(!M.mind) continue - for(var/string in splittext(lowertext(M.real_name), " ")) + for(var/string in splittext(LOWER_TEXT(M.real_name), " ")) if(!(string in ignored_words)) nameWords += string - for(var/string in splittext(lowertext(M.name), " ")) + for(var/string in splittext(LOWER_TEXT(M.name), " ")) if(!(string in ignored_words)) nameWords += string diff --git a/code/modules/admin/verbs/adminjump.dm b/code/modules/admin/verbs/adminjump.dm index dfcc5f60dd0..0248ccd9975 100644 --- a/code/modules/admin/verbs/adminjump.dm +++ b/code/modules/admin/verbs/adminjump.dm @@ -1,114 +1,66 @@ -/client/proc/jumptoarea(area/A in get_sorted_areas()) - set name = "Jump to Area" - set desc = "Area to jump to" - set category = "Admin.Game" - if(!src.holder) - to_chat(src, "Only administrators may use this command.", confidential = TRUE) +ADMIN_VERB(jump_to_area, R_ADMIN, "Jump To Area", "Jumps to the specified area.", ADMIN_CATEGORY_GAME, area/target in get_sorted_areas()) + var/turf/drop_location + top_level: + for(var/list/zlevel_turfs as anything in target.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + if(area_turf.density) + continue + drop_location = area_turf + break top_level + + if(isnull(drop_location)) + to_chat(user, span_warning("No valid drop location found in the area!")) return - if(!A) - return + user.mob.abstract_move(drop_location) + log_admin("[key_name(user)] jumped to [AREACOORD(drop_location)]") + message_admins("[key_name_admin(user)] jumped to [AREACOORD(drop_location)]") + BLACKBOX_LOG_ADMIN_VERB("Jump To Area") - var/list/turfs = list() - for (var/list/zlevel_turfs as anything in A.get_zlevel_turf_lists()) - for (var/turf/area_turf as anything in zlevel_turfs) - if(!area_turf.density) - turfs.Add(area_turf) - - if(length(turfs)) - var/turf/T = pick(turfs) - usr.forceMove(T) - log_admin("[key_name(usr)] jumped to [AREACOORD(T)]") - message_admins("[key_name_admin(usr)] jumped to [AREACOORD(T)]") - BLACKBOX_LOG_ADMIN_VERB("Jump To Area") - else - to_chat(src, "Nowhere to jump to!", confidential = TRUE) - return - - -/client/proc/jumptoturf(turf/T in world) - set name = "Jump to Turf" - set category = "Admin.Game" - if(!src.holder) - to_chat(src, "Only administrators may use this command.", confidential = TRUE) - return - - log_admin("[key_name(usr)] jumped to [AREACOORD(T)]") - message_admins("[key_name_admin(usr)] jumped to [AREACOORD(T)]") - usr.forceMove(T) +ADMIN_VERB_AND_CONTEXT_MENU(jump_to_turf, R_ADMIN, "Jump To Turf", "Jump to any turf in the game. This will lag your client.", ADMIN_CATEGORY_GAME, turf/locale in world) + log_admin("[key_name(user)] jumped to [AREACOORD(locale)]") + message_admins("[key_name_admin(user)] jumped to [AREACOORD(locale)]") + user.mob.abstract_move(locale) BLACKBOX_LOG_ADMIN_VERB("Jump To Turf") - return -/client/proc/jumptomob(mob/M in GLOB.mob_list) - set category = "Admin.Game" - set name = "Jump to Mob" +ADMIN_VERB_AND_CONTEXT_MENU(jump_to_mob, R_ADMIN, "Jump To Mob", "Jump to any mob in the game.", ADMIN_CATEGORY_GAME, mob/target in world) + user.mob.abstract_move(target.loc) + log_admin("[key_name(user)] jumped to [key_name(target)]") + message_admins("[key_name_admin(user)] jumped to [ADMIN_LOOKUPFLW(target)] at [AREACOORD(target)]") + BLACKBOX_LOG_ADMIN_VERB("Jump To Mob") - if(!src.holder) - to_chat(src, "Only administrators may use this command.", confidential = TRUE) +ADMIN_VERB(jump_to_coord, R_ADMIN, "Jump To Coordinate", "Jump to a specific coordinate in the game world.", ADMIN_CATEGORY_GAME, cx as num, cy as num, cz as num) + var/turf/where_we_droppin = locate(cx, cy, cz) + if(isnull(where_we_droppin)) + to_chat(user, span_warning("Invalid coordinates.")) return - log_admin("[key_name(usr)] jumped to [key_name(M)]") - message_admins("[key_name_admin(usr)] jumped to [ADMIN_LOOKUPFLW(M)] at [AREACOORD(M)]") - if(src.mob) - var/mob/A = src.mob - var/turf/T = get_turf(M) - if(T && isturf(T)) - BLACKBOX_LOG_ADMIN_VERB("Jump To Mob") - A.forceMove(M.loc) - else - to_chat(A, "This mob is not located in the game world.", confidential = TRUE) + user.mob.abstract_move(where_we_droppin) + message_admins("[key_name_admin(user)] jumped to coordinates [cx], [cy], [cz]") + BLACKBOX_LOG_ADMIN_VERB("Jump To Coordiate") -/client/proc/jumptocoord(tx as num, ty as num, tz as num) - set category = "Admin.Game" - set name = "Jump to Coordinate" - - if (!holder) - to_chat(src, "Only administrators may use this command.", confidential = TRUE) - return - - if(src.mob) - var/mob/A = src.mob - var/turf/T = locate(tx,ty,tz) - A.forceMove(T) - BLACKBOX_LOG_ADMIN_VERB("Jump To Coordiate") - message_admins("[key_name_admin(usr)] jumped to coordinates [tx], [ty], [tz]") - -/client/proc/jumptokey() - set category = "Admin.Game" - set name = "Jump to Key" - - if(!src.holder) - to_chat(src, "Only administrators may use this command.", confidential = TRUE) - return +ADMIN_VERB(jump_to_key, R_ADMIN, "Jump To Key", "Jump to a specific player.", ADMIN_CATEGORY_GAME) + if(!isobserver(user.mob)) + SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/admin_ghost) var/list/keys = list() for(var/mob/M in GLOB.player_list) keys += M.client - var/client/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sort_key(keys) + var/client/selection = input(user, "Please, select a player!", "Admin Jumping") as null|anything in sort_key(keys) if(!selection) - to_chat(src, "No keys found.", confidential = TRUE) + to_chat(user, "No keys found.", confidential = TRUE) return var/mob/M = selection.mob - log_admin("[key_name(usr)] jumped to [key_name(M)]") - message_admins("[key_name_admin(usr)] jumped to [ADMIN_LOOKUPFLW(M)]") - - usr.forceMove(M.loc) - + log_admin("[key_name(user)] jumped to [key_name(M)]") + message_admins("[key_name_admin(user)] jumped to [ADMIN_LOOKUPFLW(M)]") + user.mob.abstract_move(M.loc) BLACKBOX_LOG_ADMIN_VERB("Jump To Key") -/client/proc/Getmob(mob/M in GLOB.mob_list - GLOB.dummy_mob_list) - set category = "Admin.Game" - set name = "Get Mob" - set desc = "Mob to teleport" - if(!src.holder) - to_chat(src, "Only administrators may use this command.", confidential = TRUE) - return - - var/atom/loc = get_turf(usr) - M.admin_teleport(loc) +ADMIN_VERB_AND_CONTEXT_MENU(get_mob, R_ADMIN, "Get Mob", "Teleport a mob to your location.", ADMIN_CATEGORY_GAME, mob/target in world) + var/atom/loc = get_turf(user.mob) + target.admin_teleport(loc) BLACKBOX_LOG_ADMIN_VERB("Get Mob") - /// Proc to hook user-enacted teleporting behavior and keep logging of the event. /atom/movable/proc/admin_teleport(atom/new_location) if(isnull(new_location)) @@ -126,56 +78,41 @@ admin_ticket_log(src, msg) return ..() - -/client/proc/Getkey() - set category = "Admin.Game" - set name = "Get Key" - set desc = "Key to teleport" - - if(!src.holder) - to_chat(src, "Only administrators may use this command.", confidential = TRUE) - return - +ADMIN_VERB(get_key, R_ADMIN, "Get Key", "Teleport the player with the provided key to you.", ADMIN_CATEGORY_GAME) var/list/keys = list() for(var/mob/M in GLOB.player_list) keys += M.client - var/client/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sort_key(keys) + var/client/selection = input(user, "Please, select a player!", "Admin Jumping") as null|anything in sort_key(keys) if(!selection) return var/mob/M = selection.mob if(!M) return - log_admin("[key_name(usr)] teleported [key_name(M)]") - var/msg = "[key_name_admin(usr)] teleported [ADMIN_LOOKUPFLW(M)]" + log_admin("[key_name(user)] teleported [key_name(M)]") + var/msg = "[key_name_admin(user)] teleported [ADMIN_LOOKUPFLW(M)]" message_admins(msg) admin_ticket_log(M, msg) if(M) - M.forceMove(get_turf(usr)) - usr.forceMove(M.loc) + M.forceMove(get_turf(user)) BLACKBOX_LOG_ADMIN_VERB("Get Key") -/client/proc/sendmob(mob/jumper in sort_mobs()) - set category = "Admin.Game" - set name = "Send Mob" - if(!src.holder) - to_chat(src, "Only administrators may use this command.", confidential = TRUE) - return +ADMIN_VERB_AND_CONTEXT_MENU(send_mob, R_ADMIN, "Send Mob", "Teleport the specified mob to an area of your choosing.", ADMIN_CATEGORY_GAME, mob/jumper) var/list/sorted_areas = get_sorted_areas() if(!length(sorted_areas)) - to_chat(src, "No areas found.", confidential = TRUE) + to_chat(user, "No areas found.", confidential = TRUE) return - var/area/target_area = tgui_input_list(src, "Pick an area", "Send Mob", sorted_areas) + var/area/target_area = tgui_input_list(user, "Pick an area", "Send Mob", sorted_areas) if(isnull(target_area)) return if(!istype(target_area)) return var/list/turfs = get_area_turfs(target_area) if(length(turfs) && jumper.forceMove(pick(turfs))) - log_admin("[key_name(usr)] teleported [key_name(jumper)] to [AREACOORD(jumper)]") - var/msg = "[key_name_admin(usr)] teleported [ADMIN_LOOKUPFLW(jumper)] to [AREACOORD(jumper)]" + log_admin("[key_name(user)] teleported [key_name(jumper)] to [AREACOORD(jumper)]") + var/msg = "[key_name_admin(user)] teleported [ADMIN_LOOKUPFLW(jumper)] to [AREACOORD(jumper)]" message_admins(msg) admin_ticket_log(jumper, msg) else - to_chat(src, "Failed to move mob to a valid location.", confidential = TRUE) + to_chat(user, "Failed to move mob to a valid location.", confidential = TRUE) BLACKBOX_LOG_ADMIN_VERB("Send Mob") diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 529cf4d8a77..23676cd8ea9 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -13,36 +13,19 @@ // We also make SURE to fail loud, IE: if something stops the message from reaching the recipient, the sender HAS to know // If you "refactor" this to make it "cleaner" I will send you to hell -/// Allows right clicking mobs to send an admin PM to their client, forwards the selected mob's client to cmd_admin_pm -/client/proc/cmd_admin_pm_context(mob/M in GLOB.mob_list) - set category = null - set name = "Admin PM Mob" - if(!holder) - to_chat(src, - type = MESSAGE_TYPE_ADMINPM, - html = span_danger("Error: Admin-PM-Context: Only administrators may use this command."), - confidential = TRUE) - return - if(!ismob(M)) - to_chat(src, +ADMIN_VERB_ONLY_CONTEXT_MENU(cmd_admin_pm_context, R_NONE, "Admin PM Mob", mob/target in world) + if(!ismob(target)) + to_chat( + src, type = MESSAGE_TYPE_ADMINPM, html = span_danger("Error: Admin-PM-Context: Target mob is not a mob, somehow."), - confidential = TRUE) + confidential = TRUE, + ) return - cmd_admin_pm(M.client, null) + user.cmd_admin_pm(target.client, null) BLACKBOX_LOG_ADMIN_VERB("Admin PM Mob") -/// Shows a list of clients we could send PMs to, then forwards our choice to cmd_admin_pm -/client/proc/cmd_admin_pm_panel() - set category = "Admin" - set name = "Admin PM" - if(!holder) - to_chat(src, - type = MESSAGE_TYPE_ADMINPM, - html = span_danger("Error: Admin-PM-Panel: Only administrators may use this command."), - confidential = TRUE) - return - +ADMIN_VERB(cmd_admin_pm_panel, R_NONE, "Admin PM", "Show a list of clients to PM", ADMIN_CATEGORY_MAIN) var/list/targets = list() for(var/client/client in GLOB.clients) var/nametag = "" @@ -62,7 +45,7 @@ var/target = input(src,"To whom shall we send a message?", "Admin PM", null) as null|anything in sort_list(targets) if (isnull(target)) return - cmd_admin_pm(targets[target], null) + user.cmd_admin_pm(targets[target], null) BLACKBOX_LOG_ADMIN_VERB("Admin PM") /// Replys to some existing ahelp, reply to whom, which can be a client or ckey @@ -635,7 +618,7 @@ // The ticket's id var/ticket_id = ticket?.id - var/compliant_msg = trim(lowertext(message)) + var/compliant_msg = trim(LOWER_TEXT(message)) var/tgs_tagged = "[sender](TGS/External)" var/list/splits = splittext(compliant_msg, " ") var/split_size = length(splits) diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm index ad7a89a228d..87410528ab3 100644 --- a/code/modules/admin/verbs/adminsay.dm +++ b/code/modules/admin/verbs/adminsay.dm @@ -1,18 +1,12 @@ -/client/proc/cmd_admin_say(msg as text) - set category = "Admin" - set name = "Asay" //Gave this shit a shorter name so you only have to time out "asay" rather than "admin say" to use it --NeoFite - set hidden = TRUE - if(!check_rights(0)) +ADMIN_VERB(cmd_admin_say, R_NONE, "ASay", "Send a message to other admins", ADMIN_CATEGORY_MAIN, message as text) + message = emoji_parse(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)) + if(!message) return - msg = emoji_parse(copytext_char(sanitize(msg), 1, MAX_MESSAGE_LEN)) - if(!msg) - return - - if(findtext(msg, "@") || findtext(msg, "#")) - var/list/link_results = check_asay_links(msg) + if(findtext(message, "@") || findtext(message, "#")) + var/list/link_results = check_asay_links(message) if(length(link_results)) - msg = link_results[ASAY_LINK_NEW_MESSAGE_INDEX] + message = link_results[ASAY_LINK_NEW_MESSAGE_INDEX] link_results[ASAY_LINK_NEW_MESSAGE_INDEX] = null var/list/pinged_admin_clients = link_results[ASAY_LINK_PINGED_ADMINS_INDEX] for(var/iter_ckey in pinged_admin_clients) @@ -22,19 +16,19 @@ window_flash(iter_admin_client) SEND_SOUND(iter_admin_client.mob, sound('sound/misc/asay_ping.ogg')) - mob.log_talk(msg, LOG_ASAY) - msg = keywords_lookup(msg) - send_asay_to_other_server(ckey, msg) //SKYRAT EDIT ADDITION - var/asay_color = prefs.read_preference(/datum/preference/color/asay_color) + user.mob.log_talk(message, LOG_ASAY) + message = keywords_lookup(message) + send_asay_to_other_server(user.ckey, message) //SKYRAT EDIT ADDITION + var/asay_color = user.prefs.read_preference(/datum/preference/color/asay_color) var/custom_asay_color = (CONFIG_GET(flag/allow_admin_asaycolor) && asay_color) ? "" : "" - msg = "[span_adminsay("[span_prefix("ADMIN:")] [key_name(usr, 1)] [ADMIN_FLW(mob)]: [custom_asay_color][msg]")][custom_asay_color ? "":null]" + message = "[span_adminsay("[span_prefix("ADMIN:")] [key_name_admin(user)] [ADMIN_FLW(user.mob)]: [custom_asay_color][message]")][custom_asay_color ? "":null]" to_chat(GLOB.admins, type = MESSAGE_TYPE_ADMINCHAT, - html = msg, + html = message, confidential = TRUE) BLACKBOX_LOG_ADMIN_VERB("Asay") /client/proc/get_admin_say() var/msg = input(src, null, "asay \"text\"") as text|null - cmd_admin_say(msg) + SSadmin_verbs.dynamic_invoke_verb(src, /datum/admin_verb/cmd_admin_say, msg) diff --git a/code/modules/admin/verbs/atmosdebug.dm b/code/modules/admin/verbs/atmosdebug.dm index 2e73a9955f7..9f744ff0147 100644 --- a/code/modules/admin/verbs/atmosdebug.dm +++ b/code/modules/admin/verbs/atmosdebug.dm @@ -1,35 +1,27 @@ -/client/proc/atmosscan() - set category = "Mapping" - set name = "Check Plumbing" - if(!src.holder) - to_chat(src, "Only administrators may use this command.", confidential = TRUE) - return +ADMIN_VERB_VISIBILITY(atmos_debug, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(atmos_debug, R_DEBUG, "Check Plumbing", "Verifies the integrity of the plumbing network.", ADMIN_CATEGORY_MAPPING) BLACKBOX_LOG_ADMIN_VERB("Check Plumbing") //all plumbing - yes, some things might get stated twice, doesn't matter. for(var/obj/machinery/atmospherics/components/pipe as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/atmospherics/components)) if(pipe.z && (!pipe.nodes || !pipe.nodes.len || (null in pipe.nodes))) - to_chat(usr, "Unconnected [pipe.name] located at [ADMIN_VERBOSEJMP(pipe)]", confidential = TRUE) + to_chat(user, "Unconnected [pipe.name] located at [ADMIN_VERBOSEJMP(pipe)]", confidential = TRUE) //Pipes for(var/obj/machinery/atmospherics/pipe/pipe as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/atmospherics/pipe)) if(istype(pipe, /obj/machinery/atmospherics/pipe/smart) || istype(pipe, /obj/machinery/atmospherics/pipe/layer_manifold)) continue if(pipe.z && (!pipe.nodes || !pipe.nodes.len || (null in pipe.nodes))) - to_chat(usr, "Unconnected [pipe.name] located at [ADMIN_VERBOSEJMP(pipe)]", confidential = TRUE) + to_chat(user, "Unconnected [pipe.name] located at [ADMIN_VERBOSEJMP(pipe)]", confidential = TRUE) //Nodes for(var/obj/machinery/atmospherics/node1 as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/atmospherics)) for(var/obj/machinery/atmospherics/node2 in node1.nodes) if(!(node1 in node2.nodes)) - to_chat(usr, "One-way connection in [node1.name] located at [ADMIN_VERBOSEJMP(node1)]", confidential = TRUE) + to_chat(user, "One-way connection in [node1.name] located at [ADMIN_VERBOSEJMP(node1)]", confidential = TRUE) -/client/proc/powerdebug() - set category = "Mapping" - set name = "Check Power" - if(!src.holder) - to_chat(src, "Only administrators may use this command.", confidential = TRUE) - return +ADMIN_VERB_VISIBILITY(power_debug, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(power_debug, R_DEBUG, "Check Power", "Verifies the integrity of the power network.", ADMIN_CATEGORY_MAPPING) BLACKBOX_LOG_ADMIN_VERB("Check Power") var/list/results = list() @@ -56,4 +48,4 @@ var/obj/structure/cable/C = locate(/obj/structure/cable) in T.contents if(!C) results += "Unwired terminal at [ADMIN_VERBOSEJMP(term)]" - to_chat(usr, "[results.Join("\n")]", confidential = TRUE) + to_chat(user, "[results.Join("\n")]", confidential = TRUE) diff --git a/code/modules/admin/verbs/beakerpanel.dm b/code/modules/admin/verbs/beakerpanel.dm index 5ba32ae7b6c..7088fba92f1 100644 --- a/code/modules/admin/verbs/beakerpanel.dm +++ b/code/modules/admin/verbs/beakerpanel.dm @@ -60,14 +60,11 @@ reagents.add_reagent(reagenttype, amount) return container -/datum/admins/proc/beaker_panel() - set category = "Admin.Events" - set name = "Spawn reagent container" - if(!check_rights()) - return +ADMIN_VERB(beaker_panel, R_SPAWN, "Spawn Reagent Container", "Spawn a reagent container.", ADMIN_CATEGORY_EVENTS) var/datum/asset/asset_datum = get_asset_datum(/datum/asset/simple/namespaced/common) - asset_datum.send(usr) + asset_datum.send(user) //Could somebody tell me why this isn't using the browser datum, given that it copypastes all of browser datum's html + // fuck if I know, but im not touching it var/dat = {" @@ -320,4 +317,4 @@ "} - usr << browse(dat, "window=beakerpanel;size=1100x720") + user << browse(dat, "window=beakerpanel;size=1100x720") diff --git a/code/modules/admin/verbs/borgpanel.dm b/code/modules/admin/verbs/borgpanel.dm index b8fd3698a56..6a8e1efdb56 100644 --- a/code/modules/admin/verbs/borgpanel.dm +++ b/code/modules/admin/verbs/borgpanel.dm @@ -1,21 +1,6 @@ -/datum/admins/proc/open_borgopanel(borgo in GLOB.silicon_mobs) - set category = "Admin.Game" - set name = "Show Borg Panel" - set desc = "Show borg panel" - - if(!check_rights(R_ADMIN)) - return - - if (!iscyborg(borgo)) - borgo = input("Select a borg", "Select a borg", null, null) as null|anything in sort_names(GLOB.silicon_mobs) - if (!iscyborg(borgo)) - to_chat(usr, span_warning("Borg is required for borgpanel"), confidential = TRUE) - - var/datum/borgpanel/borgpanel = new(usr, borgo) - - borgpanel.ui_interact(usr) - - +ADMIN_VERB(borg_panel, R_ADMIN, "Show Borg Panel", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/living/silicon/robot/borgo) + var/datum/borgpanel/borgpanel = new(user.mob, borgo) + borgpanel.ui_interact(user.mob) /datum/borgpanel var/mob/living/silicon/robot/borg diff --git a/code/modules/admin/verbs/change_shuttle_events.dm b/code/modules/admin/verbs/change_shuttle_events.dm index 4ec8a7cd7b8..90f7e03672e 100644 --- a/code/modules/admin/verbs/change_shuttle_events.dm +++ b/code/modules/admin/verbs/change_shuttle_events.dm @@ -1,20 +1,9 @@ -///Manipulate the events that are gonna run/are running on the escape shuttle -/datum/admins/proc/change_shuttle_events() - set category = "Admin.Events" - set name = "Change Shuttle Events" - set desc = "Allows you to change the events on a shuttle." - - if (!istype(src, /datum/admins)) - src = usr.client.holder - if (!istype(src, /datum/admins)) - to_chat(usr, "Error: you are not an admin!", confidential = TRUE) - return - +ADMIN_VERB(change_shuttle_events, R_ADMIN|R_FUN, "Change Shuttle Events", "Change the events on a shuttle.", ADMIN_CATEGORY_EVENTS) //At least for now, just letting admins modify the emergency shuttle is fine var/obj/docking_port/mobile/port = SSshuttle.emergency if(!port) - to_chat(usr, span_admin("Uh oh, couldn't find the escape shuttle!")) + to_chat(user, span_admin("Uh oh, couldn't find the escape shuttle!")) var/list/options = list("Clear"="Clear") @@ -27,16 +16,16 @@ options[((event in active) ? "(Remove)" : "(Add)") + initial(event.name)] = event //Throw up an ugly menu with the shuttle events and the options to add or remove them, or clear them all - var/result = input(usr, "Choose an event to add/remove", "Shuttle Events") as null|anything in sort_list(options) + var/result = input(user, "Choose an event to add/remove", "Shuttle Events") as null|anything in sort_list(options) if(result == "Clear") port.event_list.Cut() - message_admins("[key_name_admin(usr)] has cleared the shuttle events on: [port]") + message_admins("[key_name_admin(user)] has cleared the shuttle events on: [port]") else if(options[result]) var/typepath = options[result] if(typepath in active) port.event_list.Remove(active[options[result]]) - message_admins("[key_name_admin(usr)] has removed '[active[result]]' from [port].") + message_admins("[key_name_admin(user)] has removed '[active[result]]' from [port].") else port.event_list.Add(new typepath (port)) - message_admins("[key_name_admin(usr)] has added '[typepath]' to [port].") + message_admins("[key_name_admin(user)] has added '[typepath]' to [port].") diff --git a/code/modules/admin/verbs/cinematic.dm b/code/modules/admin/verbs/cinematic.dm index b001099d283..f9e96c89cd0 100644 --- a/code/modules/admin/verbs/cinematic.dm +++ b/code/modules/admin/verbs/cinematic.dm @@ -1,14 +1,10 @@ -/client/proc/cinematic() - set name = "Cinematic" - set category = "Admin.Fun" - set desc = "Shows a cinematic." // Intended for testing but I thought it might be nice for events on the rare occasion Feel free to comment it out if it's not wanted. - set hidden = TRUE - - if(!SSticker) - return - - var/datum/cinematic/choice = tgui_input_list(usr, "Chose a cinematic to play to everyone in the server.", "Choose Cinematic", sort_list(subtypesof(/datum/cinematic), GLOBAL_PROC_REF(cmp_typepaths_asc))) +ADMIN_VERB(cinematic, R_FUN, "Cinematic", "Show a cinematic to all players.", ADMIN_CATEGORY_FUN) + var/datum/cinematic/choice = tgui_input_list( + user, + "Chose a cinematic to play to everyone in the server.", + "Choose Cinematic", + sort_list(subtypesof(/datum/cinematic), GLOBAL_PROC_REF(cmp_typepaths_asc)), + ) if(!choice || !ispath(choice, /datum/cinematic)) return - play_cinematic(choice, world) diff --git a/code/modules/admin/verbs/commandreport.dm b/code/modules/admin/verbs/commandreport.dm index 86e7ec1328b..047ef04a0b7 100644 --- a/code/modules/admin/verbs/commandreport.dm +++ b/code/modules/admin/verbs/commandreport.dm @@ -7,32 +7,19 @@ #define WIZARD_PRESET "The Wizard Federation" #define CUSTOM_PRESET "Custom Command Name" -/// Verb to change the global command name. -/client/proc/cmd_change_command_name() - set category = "Admin.Events" - set name = "Change Command Name" - - if(!check_rights(R_ADMIN)) - return - - var/input = input(usr, "Please input a new name for Central Command.", "What?", "") as text|null +ADMIN_VERB(change_command_name, R_ADMIN, "Change Command Name", "Change the name of Central Command.", ADMIN_CATEGORY_EVENTS) + var/input = input(user, "Please input a new name for Central Command.", "What?", "") as text|null if(!input) return change_command_name(input) - message_admins("[key_name_admin(src)] has changed Central Command's name to [input]") - log_admin("[key_name(src)] has changed the Central Command name to: [input]") + message_admins("[key_name_admin(user)] has changed Central Command's name to [input]") + log_admin("[key_name(user)] has changed the Central Command name to: [input]") /// Verb to open the create command report window and send command reports. -/client/proc/cmd_admin_create_centcom_report() - set category = "Admin.Events" - set name = "Create Command Report" - - if(!check_rights(R_ADMIN)) - return - +ADMIN_VERB(create_command_report, R_ADMIN, "Create Command Report", "Create a command report to be sent to the station.", ADMIN_CATEGORY_EVENTS) BLACKBOX_LOG_ADMIN_VERB("Create Command Report") - var/datum/command_report_menu/tgui = new(usr) - tgui.ui_interact(usr) + var/datum/command_report_menu/tgui = new /datum/command_report_menu(user.mob) + tgui.ui_interact(user.mob) /// Datum for holding the TGUI window for command reports. /datum/command_report_menu diff --git a/code/modules/admin/verbs/config_helpers.dm b/code/modules/admin/verbs/config_helpers.dm index 013c7b63f8a..c043274d427 100644 --- a/code/modules/admin/verbs/config_helpers.dm +++ b/code/modules/admin/verbs/config_helpers.dm @@ -1,19 +1,14 @@ -/// Verbs created to help server operators with generating certain config files. +#define GENERATE_JOB_CONFIG_VERB_DESC "Generate a job configuration (jobconfig.toml) file for the server. If TOML file already exists, will re-generate it based off the already existing config values. Will migrate from the old jobs.txt format if necessary." -/client/proc/generate_job_config() - set name = "Generate Job Configuration" - set category = "Server" - set desc = "Generate a job configuration (jobconfig.toml) file for the server. If TOML file already exists, will re-generate it based off the already existing config values. Will migrate from the old jobs.txt format if necessary." - - if(!check_rights(R_SERVER)) +ADMIN_VERB(generate_job_config, R_SERVER, "Generate Job Configuration", GENERATE_JOB_CONFIG_VERB_DESC, ADMIN_CATEGORY_SERVER) + if(tgui_alert(user, "This verb is not at all useful if you are not a server operator with access to the configuration folder. Do you wish to proceed?", "Generate jobconfig.toml for download", list("Yes", "No")) != "Yes") return - if(tgui_alert(usr, "This verb is not at all useful if you are not a server operator with access to the configuration folder. Do you wish to proceed?", "Generate jobconfig.toml for download", list("Yes", "No")) != "Yes") - return - - if(SSjob.generate_config(usr)) - to_chat(usr, span_notice("Job configuration file generated. Download prompt should appear now.")) + if(SSjob.generate_config(user)) + to_chat(user, span_notice("Job configuration file generated. Download prompt should appear now.")) else - to_chat(usr, span_warning("Job configuration file could not be generated. Check the server logs / runtimes / above warning messages for more information.")) + to_chat(user, span_warning("Job configuration file could not be generated. Check the server logs / runtimes / above warning messages for more information.")) BLACKBOX_LOG_ADMIN_VERB("Generate Job Configuration") + +#undef GENERATE_JOB_CONFIG_VERB_DESC diff --git a/code/modules/admin/verbs/deadsay.dm b/code/modules/admin/verbs/deadsay.dm index 032a4d4fa48..c330618d8b4 100644 --- a/code/modules/admin/verbs/deadsay.dm +++ b/code/modules/admin/verbs/deadsay.dm @@ -1,39 +1,30 @@ -/client/proc/dsay(msg as text) - set category = "Admin.Game" - set name = "Dsay" - set hidden = TRUE - if(!holder) - to_chat(src, "Only administrators may use this command.", confidential = TRUE) - return - if(!mob) - return - if(prefs.muted & MUTE_DEADCHAT) - to_chat(src, span_danger("You cannot send DSAY messages (muted)."), confidential = TRUE) + +ADMIN_VERB(dsay, R_NONE, "DSay", "Speak to the dead.", ADMIN_CATEGORY_GAME, message as text) + if(user.prefs.muted & MUTE_DEADCHAT) + to_chat(user, span_danger("You cannot send DSAY messages (muted)."), confidential = TRUE) return - if (handle_spam_prevention(msg,MUTE_DEADCHAT)) + if (user.handle_spam_prevention(message,MUTE_DEADCHAT)) return - msg = copytext_char(sanitize(msg), 1, MAX_MESSAGE_LEN) - mob.log_talk(msg, LOG_DSAY) + message = copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN) + user.mob.log_talk(message, LOG_DSAY) - if (!msg) + if (!message) return - var/rank_name = holder.rank_names() - var/admin_name = key - if(holder.fakekey) + var/rank_name = user.holder.rank_names() + var/admin_name = user.key + if(user.holder.fakekey) rank_name = pick(strings("admin_nicknames.json", "ranks", "config")) admin_name = pick(strings("admin_nicknames.json", "names", "config")) var/name_and_rank = "[span_tooltip(rank_name, "STAFF")] ([admin_name])" - deadchat_broadcast("[span_prefix("DEAD:")] [name_and_rank] says, \"[emoji_parse(msg)]\"") + deadchat_broadcast("[span_prefix("DEAD:")] [name_and_rank] says, \"[emoji_parse(message)]\"") BLACKBOX_LOG_ADMIN_VERB("Dsay") /client/proc/get_dead_say() var/msg = input(src, null, "dsay \"text\"") as text|null - if (isnull(msg)) return - - dsay(msg) + SSadmin_verbs.dynamic_invoke_verb(src, /datum/admin_verb/dsay, msg) diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 35b1baa063d..e56eb1e5101 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -1,40 +1,27 @@ -/client/proc/Debug2() - set category = "Debug" - set name = "Debug-Game" - if(!check_rights(R_DEBUG)) - return - - if(GLOB.Debug2) - GLOB.Debug2 = 0 - message_admins("[key_name(src)] toggled debugging off.") - log_admin("[key_name(src)] toggled debugging off.") - else - GLOB.Debug2 = 1 - message_admins("[key_name(src)] toggled debugging on.") - log_admin("[key_name(src)] toggled debugging on.") - +ADMIN_VERB(toggle_game_debug, R_DEBUG, "Debug-Game", "Toggles game debugging.", ADMIN_CATEGORY_DEBUG) + GLOB.Debug2 = !GLOB.Debug2 + var/message = "toggled debugging [(GLOB.Debug2 ? "ON" : "OFF")]" + message_admins("[key_name_admin(user)] [message].") + log_admin("[key_name(user)] [message].") BLACKBOX_LOG_ADMIN_VERB("Toggle Debug Two") -/client/proc/Cell() - set category = "Debug" - set name = "Air Status in Location" - if(!mob) +ADMIN_VERB_VISIBILITY(air_status, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(air_status, R_DEBUG, "Air Status In Location", "Gets the air status for your current turf.", ADMIN_CATEGORY_DEBUG) + var/turf/user_turf = get_turf(user.mob) + if(!isturf(user_turf)) return - var/turf/T = get_turf(mob) - if(!isturf(T)) - return - atmos_scan(user=usr, target=T, silent=TRUE) + atmos_scan(user.mob, user_turf, silent = TRUE) BLACKBOX_LOG_ADMIN_VERB("Air Status In Location") -/client/proc/cmd_admin_robotize(mob/M in GLOB.mob_list) - set category = "Admin.Fun" - set name = "Make Cyborg" - +ADMIN_VERB(cmd_admin_robotize, R_FUN, "Make Cyborg", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/target) if(!SSticker.HasRoundStarted()) - tgui_alert(usr,"Wait until the game starts") + tgui_alert(user, "Wait until the game starts") return - log_admin("[key_name(src)] has robotized [M.key].") - INVOKE_ASYNC(M, TYPE_PROC_REF(/mob, Robotize)) + if(issilicon(target)) + tgui_alert(user, "They are already a cyborg.") + return + log_admin("[key_name(user)] has robotized [target.key].") + INVOKE_ASYNC(target, TYPE_PROC_REF(/mob, Robotize)) /client/proc/poll_type_to_del(search_string) var/list/types = get_fancy_list_of_atom_types() @@ -50,13 +37,8 @@ return return types[key] -//TODO: merge the vievars version into this or something maybe mayhaps -/client/proc/cmd_debug_del_all(object as text) - set category = "Debug" - set name = "Del-All" - - var/type_to_del = poll_type_to_del(object) - +ADMIN_VERB(cmd_del_all, R_DEBUG|R_SPAWN, "Del-All", "Delete all datums with the specified type.", ADMIN_CATEGORY_DEBUG, object as text) + var/type_to_del = user.poll_type_to_del(object) if(!type_to_del) return @@ -66,16 +48,12 @@ counter++ qdel(O) CHECK_TICK - log_admin("[key_name(src)] has deleted all ([counter]) instances of [type_to_del].") - message_admins("[key_name_admin(src)] has deleted all ([counter]) instances of [type_to_del].") + log_admin("[key_name(user)] has deleted all ([counter]) instances of [type_to_del].") + message_admins("[key_name_admin(user)] has deleted all ([counter]) instances of [type_to_del].") BLACKBOX_LOG_ADMIN_VERB("Delete All") -/client/proc/cmd_debug_force_del_all(object as text) - set category = "Debug" - set name = "Force-Del-All" - - var/type_to_del = poll_type_to_del(object) - +ADMIN_VERB(cmd_del_all_force, R_DEBUG|R_SPAWN, "Force-Del-All", "Forcibly delete all datums with the specified type.", ADMIN_CATEGORY_DEBUG, object as text) + var/type_to_del = user.poll_type_to_del(object) if(!type_to_del) return @@ -85,29 +63,25 @@ counter++ qdel(O, force = TRUE) CHECK_TICK - log_admin("[key_name(src)] has force-deleted all ([counter]) instances of [type_to_del].") - message_admins("[key_name_admin(src)] has force-deleted all ([counter]) instances of [type_to_del].") + log_admin("[key_name(user)] has force-deleted all ([counter]) instances of [type_to_del].") + message_admins("[key_name_admin(user)] has force-deleted all ([counter]) instances of [type_to_del].") BLACKBOX_LOG_ADMIN_VERB("Force-Delete All") -/client/proc/cmd_debug_hard_del_all(object as text) - set category = "Debug" - set name = "Hard-Del-All" - - var/type_to_del = poll_type_to_del(object) - +ADMIN_VERB(cmd_del_all_hard, R_DEBUG|R_SPAWN, "Hard-Del-All", "Hard delete all datums with the specified type.", ADMIN_CATEGORY_DEBUG, object as text) + var/type_to_del = user.poll_type_to_del(object) if(!type_to_del) return - var/choice = alert("ARE YOU SURE that you want to hard delete this type? It will cause MASSIVE lag.", "Hoooo lad what happen?", "Yes", "No") + var/choice = alert(user, "ARE YOU SURE that you want to hard delete this type? It will cause MASSIVE lag.", "Hoooo lad what happen?", "Yes", "No") if(choice != "Yes") return - choice = alert("Do you want to pre qdelete the atom? This will speed things up significantly, but may break depending on your level of fuckup.", "How do you even get it that bad", "Yes", "No") + choice = alert(user, "Do you want to pre qdelete the atom? This will speed things up significantly, but may break depending on your level of fuckup.", "How do you even get it that bad", "Yes", "No") var/should_pre_qdel = TRUE if(choice == "No") should_pre_qdel = FALSE - choice = alert("Ok one last thing, do you want to yield to the game? or do it all at once. These are hard deletes remember.", "Jesus christ man", "Yield", "Ignore the server") + choice = alert(user, "Ok one last thing, do you want to yield to the game? or do it all at once. These are hard deletes remember.", "Jesus christ man", "Yield", "Ignore the server") var/should_check_tick = TRUE if(choice == "Ignore the server") should_check_tick = FALSE @@ -129,24 +103,20 @@ qdel(O) del(O) CHECK_TICK - log_admin("[key_name(src)] has hard deleted all ([counter]) instances of [type_to_del].") - message_admins("[key_name_admin(src)] has hard deleted all ([counter]) instances of [type_to_del].") + log_admin("[key_name(user)] has hard deleted all ([counter]) instances of [type_to_del].") + message_admins("[key_name_admin(user)] has hard deleted all ([counter]) instances of [type_to_del].") BLACKBOX_LOG_ADMIN_VERB("Hard Delete All") -/client/proc/cmd_debug_make_powernets() - set category = "Debug" - set name = "Make Powernets" +ADMIN_VERB(cmd_debug_make_powernets, R_DEBUG|R_SERVER, "Make Powernets", "Regenerates all powernets for all cables.", ADMIN_CATEGORY_DEBUG) SSmachines.makepowernets() - log_admin("[key_name(src)] has remade the powernet. makepowernets() called.") - message_admins("[key_name_admin(src)] has remade the powernets. makepowernets() called.") + log_admin("[key_name(user)] has remade the powernet. makepowernets() called.") + message_admins("[key_name_admin(user)] has remade the powernets. makepowernets() called.") BLACKBOX_LOG_ADMIN_VERB("Make Powernets") -/client/proc/cmd_admin_grantfullaccess(mob/M in GLOB.mob_list) - set category = "Debug" - set name = "Grant Full Access" - +ADMIN_VERB_VISIBILITY(cmd_admin_grantfullaccess, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(cmd_admin_grantfullaccess, R_DEBUG, "Grant Full Access", "Grant full access to a mob.", ADMIN_CATEGORY_DEBUG, mob/M in world) if(!SSticker.HasRoundStarted()) - tgui_alert(usr,"Wait until the game starts") + tgui_alert(user, "Wait until the game starts") return if(ishuman(M)) var/mob/living/carbon/human/H = M @@ -180,51 +150,44 @@ H.equip_to_slot(id, ITEM_SLOT_ID) else - tgui_alert(usr,"Invalid mob") + tgui_alert(user,"Invalid mob") BLACKBOX_LOG_ADMIN_VERB("Grant Full Access") - log_admin("[key_name(src)] has granted [M.key] full access.") - message_admins(span_adminnotice("[key_name_admin(usr)] has granted [M.key] full access.")) - -/client/proc/cmd_assume_direct_control(mob/M in GLOB.mob_list) - set category = "Admin.Game" - set name = "Assume direct control" - set desc = "Direct intervention" + log_admin("[key_name(user)] has granted [M.key] full access.") + message_admins(span_adminnotice("[key_name_admin(user)] has granted [M.key] full access.")) +ADMIN_VERB(cmd_assume_direct_control, R_ADMIN, "Assume Direct Control", "Assume direct control of a mob.", ADMIN_CATEGORY_DEBUG, mob/M) if(M.ckey) - if(tgui_alert(usr,"This mob is being controlled by [M.key]. Are you sure you wish to assume control of it? [M.key] will be made a ghost.",,list("Yes","No")) != "Yes") + if(tgui_alert(user,"This mob is being controlled by [M.key]. Are you sure you wish to assume control of it? [M.key] will be made a ghost.",,list("Yes","No")) != "Yes") return if(!M || QDELETED(M)) - to_chat(usr, span_warning("The target mob no longer exists.")) + to_chat(user, span_warning("The target mob no longer exists.")) return - message_admins(span_adminnotice("[key_name_admin(usr)] assumed direct control of [M].")) - log_admin("[key_name(usr)] assumed direct control of [M].") - var/mob/adminmob = mob + message_admins(span_adminnotice("[key_name_admin(user)] assumed direct control of [M].")) + log_admin("[key_name(user)] assumed direct control of [M].") + var/mob/adminmob = user.mob if(M.ckey) M.ghostize(FALSE) - M.key = key - init_verbs() + M.key = user.key + user.init_verbs() if(isobserver(adminmob)) qdel(adminmob) BLACKBOX_LOG_ADMIN_VERB("Assume Direct Control") -/client/proc/cmd_give_direct_control(mob/M in GLOB.mob_list) - set category = "Admin.Game" - set name = "Give direct control" - +ADMIN_VERB(cmd_give_direct_control, R_ADMIN, "Give Direct Control", "Give direct control of a mob to another player.", ADMIN_CATEGORY_GAME, mob/M) if(!M) return if(M.ckey) - if(tgui_alert(usr,"This mob is being controlled by [M.key]. Are you sure you wish to give someone else control of it? [M.key] will be made a ghost.",,list("Yes","No")) != "Yes") + if(tgui_alert(user,"This mob is being controlled by [M.key]. Are you sure you wish to give someone else control of it? [M.key] will be made a ghost.",,list("Yes","No")) != "Yes") return - var/client/newkey = input(src, "Pick the player to put in control.", "New player") as null|anything in sort_list(GLOB.clients) + var/client/newkey = input(user, "Pick the player to put in control.", "New player") as null|anything in sort_list(GLOB.clients) if(isnull(newkey)) return var/mob/oldmob = newkey.mob var/delmob = FALSE - if((isobserver(oldmob) || tgui_alert(usr,"Do you want to delete [newkey]'s old mob?","Delete?",list("Yes","No")) != "No")) + if((isobserver(oldmob) || tgui_alert(user,"Do you want to delete [newkey]'s old mob?","Delete?",list("Yes","No")) != "No")) delmob = TRUE if(!M || QDELETED(M)) - to_chat(usr, span_warning("The target mob no longer exists, aborting.")) + to_chat(user, span_warning("The target mob no longer exists, aborting.")) return if(M.ckey) M.ghostize(FALSE) @@ -232,14 +195,12 @@ M.client?.init_verbs() if(delmob) qdel(oldmob) - message_admins(span_adminnotice("[key_name_admin(usr)] gave away direct control of [M] to [newkey].")) - log_admin("[key_name(usr)] gave away direct control of [M] to [newkey].") + message_admins(span_adminnotice("[key_name_admin(user)] gave away direct control of [M] to [newkey].")) + log_admin("[key_name(user)] gave away direct control of [M] to [newkey].") BLACKBOX_LOG_ADMIN_VERB("Give Direct Control") -/client/proc/cmd_admin_areatest(on_station, filter_maint) - set category = "Mapping" - set name = "Test Areas" - +ADMIN_VERB_VISIBILITY(cmd_admin_areatest, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(cmd_admin_areatest, R_DEBUG, "Test Areas", "Tests the areas for various machinery.", ADMIN_CATEGORY_MAPPING, on_station as num, filter_maint as num) var/list/dat = list() var/list/areas_all = list() var/list/areas_with_APC = list() @@ -270,7 +231,7 @@ )) if(SSticker.current_state == GAME_STATE_STARTUP) - to_chat(usr, "Game still loading, please hold!", confidential = TRUE) + to_chat(user, "Game still loading, please hold!", confidential = TRUE) return var/log_message @@ -283,8 +244,8 @@ dat += "Maintenance Areas Filtered Out" log_message += ", with no maintenance areas" - message_admins(span_adminnotice("[key_name_admin(usr)] used the Test Areas debug command checking [log_message].")) - log_admin("[key_name(usr)] used the Test Areas debug command checking [log_message].") + message_admins(span_adminnotice("[key_name_admin(user)] used the Test Areas debug command checking [log_message].")) + log_admin("[key_name(user)] used the Test Areas debug command checking [log_message].") for(var/area/A as anything in GLOB.areas) if(on_station) @@ -425,28 +386,23 @@ if(!(areas_with_APC.len || areas_with_multiple_APCs.len || areas_with_air_alarm.len || areas_with_RC.len || areas_with_light.len || areas_with_LS.len || areas_with_intercom.len || areas_with_camera.len)) dat += "No problem areas!" - var/datum/browser/popup = new(usr, "testareas", "Test Areas", 500, 750) + var/datum/browser/popup = new(user.mob, "testareas", "Test Areas", 500, 750) popup.set_content(dat.Join()) popup.open() +ADMIN_VERB_VISIBILITY(cmd_admin_areatest_station, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(cmd_admin_areatest_station, R_DEBUG, "Test Areas (STATION ONLY)", "Tests the areas for various machinery on station z-levels.", ADMIN_CATEGORY_MAPPING) + SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/cmd_admin_areatest, /* on_station = */ TRUE) -/client/proc/cmd_admin_areatest_station() - set category = "Mapping" - set name = "Test Areas (STATION ONLY)" - cmd_admin_areatest(TRUE) +ADMIN_VERB_VISIBILITY(cmd_admin_areatest_station_no_maintenance, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(cmd_admin_areatest_station_no_maintenance, R_DEBUG, "Test Areas (STATION - NO MAINT)", "Tests the areas for various machinery on station z-levels, excluding maintenance areas.", ADMIN_CATEGORY_MAPPING) + SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/cmd_admin_areatest, /* on_station = */ TRUE, /* filter_maint = */ TRUE) -/client/proc/cmd_admin_areatest_station_no_maintenance() - set category = "Mapping" - set name = "Test Areas (STATION - NO MAINT)" - cmd_admin_areatest(on_station = TRUE, filter_maint = TRUE) - -/client/proc/cmd_admin_areatest_all() - set category = "Mapping" - set name = "Test Areas (ALL)" - cmd_admin_areatest(FALSE) +ADMIN_VERB_VISIBILITY(cmd_admin_areatest_all, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(cmd_admin_areatest_all, R_DEBUG, "Test Areas (ALL)", "Tests the areas for various machinery on all z-levels.", ADMIN_CATEGORY_MAPPING) + SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/cmd_admin_areatest) /client/proc/robust_dress_shop() - var/list/baseoutfits = list("Naked","Custom","As Job...", "As Plasmaman...") var/list/outfits = list() var/list/paths = subtypesof(/datum/outfit) - typesof(/datum/outfit/job) - typesof(/datum/outfit/plasmaman) @@ -497,52 +453,29 @@ return dresscode -/client/proc/cmd_admin_rejuvenate(mob/living/M in GLOB.mob_list) - set category = "Debug" - set name = "Rejuvenate" - - if(!check_rights(R_ADMIN)) - return - - if(!mob) - return +ADMIN_VERB_ONLY_CONTEXT_MENU(cmd_admin_rejuvenate, R_ADMIN, "Rejuvenate", mob/living/M in world) if(!istype(M)) - tgui_alert(usr,"Cannot revive a ghost") + tgui_alert(user,"Cannot revive a ghost") return M.revive(ADMIN_HEAL_ALL) - log_admin("[key_name(usr)] healed / revived [key_name(M)]") - var/msg = span_danger("Admin [key_name_admin(usr)] healed / revived [ADMIN_LOOKUPFLW(M)]!") + log_admin("[key_name(user)] healed / revived [key_name(M)]") + var/msg = span_danger("Admin [key_name_admin(user)] healed / revived [ADMIN_LOOKUPFLW(M)]!") message_admins(msg) admin_ticket_log(M, msg) BLACKBOX_LOG_ADMIN_VERB("Rejuvenate") -/client/proc/cmd_admin_delete(atom/A as obj|mob|turf in world) - set category = "Debug" - set name = "Delete" +ADMIN_VERB_AND_CONTEXT_MENU(cmd_admin_delete, R_DEBUG|R_SPAWN, "Delete", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, atom/target as obj|mob|turf in world) + user.admin_delete(target) - if(!check_rights(R_SPAWN|R_DEBUG)) - return - - admin_delete(A) - -/client/proc/cmd_admin_check_contents(mob/living/M in GLOB.mob_list) - set category = "Debug" - set name = "Check Contents" - - var/list/L = M.get_contents() - for(var/t in L) - to_chat(usr, "[t] [ADMIN_VV(t)] [ADMIN_TAG(t)]", confidential = TRUE) +ADMIN_VERB_AND_CONTEXT_MENU(cmd_check_contents, R_ADMIN, "Check Contents", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, mob/living/mob) + var/list/mob_contents = mob.get_contents() + for(var/content in mob_contents) + to_chat(user, "[content] [ADMIN_VV(content)] [ADMIN_TAG(content)]", confidential = TRUE) BLACKBOX_LOG_ADMIN_VERB("Check Contents") -/client/proc/modify_goals() - set category = "Debug" - set name = "Modify goals" - - if(!check_rights(R_ADMIN)) - return - - holder.modify_goals() +ADMIN_VERB(modify_goals, R_ADMIN, "Modify Goals", "Modify the station goals for the shift.", ADMIN_CATEGORY_DEBUG) + user.holder.modify_goals() /datum/admins/proc/modify_goals() var/dat = "" @@ -551,34 +484,27 @@ dat += "
    Add New Goal" usr << browse(dat, "window=goals;size=400x400") -/client/proc/cmd_debug_mob_lists() - set category = "Debug" - set name = "Debug Mob Lists" - set desc = "For when you just gotta know" - var/chosen_list = tgui_input_list(usr, "Which list?", "Select List", list("Players","Admins","Mobs","Living Mobs","Dead Mobs","Clients","Joined Clients")) +ADMIN_VERB(debug_mob_lists, R_DEBUG, "Debug Mob Lists", "For when you just gotta know.", ADMIN_CATEGORY_DEBUG) + var/chosen_list = tgui_input_list(user, "Which list?", "Select List", list("Players","Admins","Mobs","Living Mobs","Dead Mobs","Clients","Joined Clients")) if(isnull(chosen_list)) return switch(chosen_list) if("Players") - to_chat(usr, jointext(GLOB.player_list,","), confidential = TRUE) + to_chat(user, jointext(GLOB.player_list,","), confidential = TRUE) if("Admins") - to_chat(usr, jointext(GLOB.admins,","), confidential = TRUE) + to_chat(user, jointext(GLOB.admins,","), confidential = TRUE) if("Mobs") - to_chat(usr, jointext(GLOB.mob_list,","), confidential = TRUE) + to_chat(user, jointext(GLOB.mob_list,","), confidential = TRUE) if("Living Mobs") - to_chat(usr, jointext(GLOB.alive_mob_list,","), confidential = TRUE) + to_chat(user, jointext(GLOB.alive_mob_list,","), confidential = TRUE) if("Dead Mobs") - to_chat(usr, jointext(GLOB.dead_mob_list,","), confidential = TRUE) + to_chat(user, jointext(GLOB.dead_mob_list,","), confidential = TRUE) if("Clients") - to_chat(usr, jointext(GLOB.clients,","), confidential = TRUE) + to_chat(user, jointext(GLOB.clients,","), confidential = TRUE) if("Joined Clients") - to_chat(usr, jointext(GLOB.joined_player_list,","), confidential = TRUE) - -/client/proc/cmd_display_del_log() - set category = "Debug" - set name = "Display del() Log" - set desc = "Display del's log of everything that's passed through it." + to_chat(user, jointext(GLOB.joined_player_list,","), confidential = TRUE) +ADMIN_VERB(del_log, R_DEBUG, "Display del() Log", "Display del's log of everything that's passed through it.", ADMIN_CATEGORY_DEBUG) var/list/dellog = list("List of things that have gone through qdel this round

      ") sortTim(SSgarbage.items, cmp=/proc/cmp_qdel_item_time, associative = TRUE) for(var/path in SSgarbage.items) @@ -609,37 +535,19 @@ dellog += "
    " - usr << browse(dellog.Join(), "window=dellog") + user << browse(dellog.Join(), "window=dellog") -/client/proc/cmd_display_overlay_log() - set category = "Debug" - set name = "Display overlay Log" - set desc = "Display SSoverlays log of everything that's passed through it." +ADMIN_VERB(display_overlay_log, R_DEBUG, "Display Overlay Log", "Display SSoverlays log of everything that's passed through it.", ADMIN_CATEGORY_DEBUG) + render_stats(SSoverlays.stats, user) - render_stats(SSoverlays.stats, src) +ADMIN_VERB(init_log, R_DEBUG, "Display Initialize() Log", "Displays a list of things that didn't handle Initialize() properly.", ADMIN_CATEGORY_DEBUG) + user << browse(replacetext(SSatoms.InitLog(), "\n", "
    "), "window=initlog") -/client/proc/cmd_display_init_log() - set category = "Debug" - set name = "Display Initialize() Log" - set desc = "Displays a list of things that didn't handle Initialize() properly" +ADMIN_VERB(debug_color_test, R_DEBUG, "Colorblind Testing", "Change your view to a budget version of colorblindness to test for usability.", ADMIN_CATEGORY_DEBUG) + user.holder.color_test.ui_interact(user.mob) - usr << browse(replacetext(SSatoms.InitLog(), "\n", "
    "), "window=initlog") - -/client/proc/open_colorblind_test() - set category = "Debug" - set name = "Colorblind Testing" - set desc = "Change your view to a budget version of colorblindness to test for usability" - - if(!holder) - return - holder.color_test.ui_interact(mob) - -/client/proc/debug_plane_masters() - set category = "Debug" - set name = "Edit/Debug Planes" - set desc = "Edit and visualize plane masters and their connections (relays)" - - edit_plane_masters() +ADMIN_VERB(debug_plane_masters, R_DEBUG, "Edit/Debug Planes", "Edit and visualize plane masters and their connections (relays).", ADMIN_CATEGORY_DEBUG) + user.edit_plane_masters() /client/proc/edit_plane_masters(mob/debug_on) if(!holder) @@ -651,21 +559,10 @@ holder.plane_debug.set_mirroring(FALSE) holder.plane_debug.ui_interact(mob) -/client/proc/debug_huds(i as num) - set category = "Debug" - set name = "Debug HUDs" - set desc = "Debug the data or antag HUDs" +ADMIN_VERB(debug_huds, R_DEBUG, "Debug HUDs", "Debug the data or antag HUDs.", ADMIN_CATEGORY_DEBUG, i as num) + SSadmin_verbs.dynamic_invoke_verb(user, /datum/admin_verb/debug_variables, GLOB.huds[i]) - if(!holder) - return - debug_variables(GLOB.huds[i]) - -/client/proc/jump_to_ruin() - set category = "Debug" - set name = "Jump to Ruin" - set desc = "Displays a list of all placed ruins to teleport to." - if(!holder) - return +ADMIN_VERB(jump_to_ruin, R_DEBUG, "Jump to Ruin", "Displays a list of all placed ruins to teleport to.", ADMIN_CATEGORY_DEBUG) var/list/names = list() for(var/obj/effect/landmark/ruin/ruin_landmark as anything in GLOB.ruin_landmarks) var/datum/map_template/ruin/template = ruin_landmark.ruin_template @@ -680,23 +577,17 @@ names[name] = ruin_landmark - var/ruinname = tgui_input_list(usr, "Select ruin", "Jump to Ruin", sort_list(names)) - + var/ruinname = tgui_input_list(user, "Select ruin", "Jump to Ruin", sort_list(names)) var/obj/effect/landmark/ruin/landmark = names[ruinname] - - if(istype(landmark)) - var/datum/map_template/ruin/template = landmark.ruin_template - usr.forceMove(get_turf(landmark)) - to_chat(usr, span_name("[template.name]"), confidential = TRUE) - to_chat(usr, "[template.description]", confidential = TRUE) - -/client/proc/place_ruin() - set category = "Debug" - set name = "Spawn Ruin" - set desc = "Attempt to randomly place a specific ruin." - if (!holder) + if(!istype(landmark)) return + var/datum/map_template/ruin/template = landmark.ruin_template + user.mob.forceMove(get_turf(landmark)) + to_chat(user, span_name("[template.name]"), confidential = TRUE) + to_chat(user, "[template.description]", confidential = TRUE) +ADMIN_VERB_VISIBILITY(place_ruin, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(place_ruin, R_DEBUG, "Spawn Ruin", "Attempt to randomly place a specific ruin.", ADMIN_CATEGORY_MAPPING) var/list/exists = list() for(var/landmark in GLOB.ruin_landmarks) var/obj/effect/landmark/ruin/L = landmark @@ -714,15 +605,15 @@ themed_names[name] = list(ruin, theme, list(ruin.default_area)) names += sort_list(themed_names) - var/ruinname = tgui_input_list(usr, "Select ruin", "Spawn Ruin", sort_list(names)) + var/ruinname = tgui_input_list(user, "Select ruin", "Spawn Ruin", sort_list(names)) var/data = names[ruinname] if (!data) return var/datum/map_template/ruin/template = data[1] if (exists[template]) - var/response = tgui_alert(usr,"There is already a [template] in existence.", "Spawn Ruin", list("Jump", "Place Another", "Cancel")) + var/response = tgui_alert(user,"There is already a [template] in existence.", "Spawn Ruin", list("Jump", "Place Another", "Cancel")) if (response == "Jump") - usr.forceMove(get_turf(exists[template])) + user.mob.forceMove(get_turf(exists[template])) return else if (response == "Cancel") return @@ -731,25 +622,17 @@ seedRuins(SSmapping.levels_by_trait(data[2]), max(1, template.cost), data[3], list(ruinname = template)) if (GLOB.ruin_landmarks.len > len) var/obj/effect/landmark/ruin/landmark = GLOB.ruin_landmarks[GLOB.ruin_landmarks.len] - log_admin("[key_name(src)] randomly spawned ruin [ruinname] at [COORD(landmark)].") - usr.forceMove(get_turf(landmark)) - to_chat(src, span_name("[template.name]"), confidential = TRUE) - to_chat(src, "[template.description]", confidential = TRUE) + log_admin("[key_name(user)] randomly spawned ruin [ruinname] at [COORD(landmark)].") + user.mob.forceMove(get_turf(landmark)) + to_chat(user, span_name("[template.name]"), confidential = TRUE) + to_chat(user, "[template.description]", confidential = TRUE) else - to_chat(src, span_warning("Failed to place [template.name]."), confidential = TRUE) + to_chat(user, span_warning("Failed to place [template.name]."), confidential = TRUE) -/client/proc/unload_ctf() - set category = "Debug" - set name = "Unload CTF" - set desc = "Despawns the majority of CTF" - - toggle_id_ctf(usr, CTF_GHOST_CTF_GAME_ID, unload=TRUE) - -/client/proc/run_empty_query(val as num) - set category = "Debug" - set name = "Run empty query" - set desc = "Amount of queries to run" +ADMIN_VERB(unload_ctf, R_DEBUG, "Unload CTF", "Despawns the majority of CTF.", ADMIN_CATEGORY_DEBUG) + toggle_id_ctf(user, CTF_GHOST_CTF_GAME_ID, unload=TRUE) +ADMIN_VERB(run_empty_query, R_DEBUG, "Run Empty Query", "Runs a specified number of empty queries.", ADMIN_CATEGORY_DEBUG, val as num) var/list/queries = list() for(var/i in 1 to val) var/datum/db_query/query = SSdbcore.NewQuery("NULL") @@ -761,45 +644,31 @@ qdel(query) queries.Cut() - message_admins("[key_name_admin(src)] ran [val] empty queries.") + message_admins("[key_name_admin(user)] ran [val] empty queries.") -/client/proc/clear_dynamic_transit() - set category = "Debug" - set name = "Clear Dynamic Turf Reservations" - set desc = "Deallocates all reserved space, restoring it to round start conditions." - if(!holder) - return - var/answer = tgui_alert(usr,"WARNING: THIS WILL WIPE ALL RESERVED SPACE TO A CLEAN SLATE! ANY MOVING SHUTTLES, ELEVATORS, OR IN-PROGRESS PHOTOGRAPHY WILL BE DELETED!", "Really wipe dynamic turfs?", list("YES", "NO")) +ADMIN_VERB(clear_turf_reservations, R_DEBUG, "Clear Dynamic Turf Reservations", "Deallocates all reserved space, restoring it to round start conditions.", ADMIN_CATEGORY_DEBUG) + var/answer = tgui_alert( + user, + "WARNING: THIS WILL WIPE ALL RESERVED SPACE TO A CLEAN SLATE! ANY MOVING SHUTTLES, ELEVATORS, OR IN-PROGRESS PHOTOGRAPHY WILL BE DELETED!", + "Really wipe dynamic turfs?", + list("YES", "NO"), + ) if(answer != "YES") return - message_admins(span_adminnotice("[key_name_admin(src)] cleared dynamic transit space.")) - BLACKBOX_LOG_ADMIN_VERB("Clear Dynamic Transit") - log_admin("[key_name(src)] cleared dynamic transit space.") + message_admins(span_adminnotice("[key_name_admin(user)] cleared dynamic transit space.")) + BLACKBOX_LOG_ADMIN_VERB("Clear Dynamic Turf Reservations") + log_admin("[key_name(user)] cleared dynamic turf reservations.") SSmapping.wipe_reservations() //this goes after it's logged, incase something horrible happens. -/client/proc/toggle_medal_disable() - set category = "Debug" - set name = "Toggle Medal Disable" - set desc = "Toggles the safety lock on trying to contact the medal hub." - - if(!check_rights(R_DEBUG)) - return - +ADMIN_VERB(toggle_medal_disable, R_DEBUG, "Toggle Medal Disable", "Toggles the safety lock on trying to contact the medal hub.", ADMIN_CATEGORY_DEBUG) SSachievements.achievements_enabled = !SSachievements.achievements_enabled - message_admins(span_adminnotice("[key_name_admin(src)] [SSachievements.achievements_enabled ? "disabled" : "enabled"] the medal hub lockout.")) + message_admins(span_adminnotice("[key_name_admin(user)] [SSachievements.achievements_enabled ? "disabled" : "enabled"] the medal hub lockout.")) BLACKBOX_LOG_ADMIN_VERB("Toggle Medal Disable") - log_admin("[key_name(src)] [SSachievements.achievements_enabled ? "disabled" : "enabled"] the medal hub lockout.") + log_admin("[key_name(user)] [SSachievements.achievements_enabled ? "disabled" : "enabled"] the medal hub lockout.") -/client/proc/view_runtimes() - set category = "Debug" - set name = "View Runtimes" - set desc = "Open the runtime Viewer" - - if(!holder) - return - - GLOB.error_cache.show_to(src) +ADMIN_VERB(view_runtimes, R_DEBUG, "View Runtimes", "Opens the runtime viewer.", ADMIN_CATEGORY_DEBUG) + GLOB.error_cache.show_to(user) // The runtime viewer has the potential to crash the server if there's a LOT of runtimes // this has happened before, multiple times, so we'll just leave an alert on it @@ -808,80 +677,54 @@ if(GLOB.total_runtimes >= 100000) warning = "There are a TON of runtimes, clicking any button (especially \"linear\") WILL LIKELY crash the server" // Not using TGUI alert, because it's view runtimes, stuff is probably broken - alert(usr, "[warning]. Proceed with caution. If you really need to see the runtimes, download the runtime log and view it in a text editor.", "HEED THIS WARNING CAREFULLY MORTAL") - -/client/proc/pump_random_event() - set category = "Debug" - set name = "Pump Random Event" - set desc = "Schedules the event subsystem to fire a new random event immediately. Some events may fire without notification." - if(!holder) - return + alert(user, "[warning]. Proceed with caution. If you really need to see the runtimes, download the runtime log and view it in a text editor.", "HEED THIS WARNING CAREFULLY MORTAL") +ADMIN_VERB(pump_random_event, R_DEBUG, "Pump Random Event", "Schedules the event subsystem to fire a new random event immediately. Some events may fire without notification.", ADMIN_CATEGORY_DEBUG) SSevents.scheduled = world.time - message_admins(span_adminnotice("[key_name_admin(src)] pumped a random event.")) + message_admins(span_adminnotice("[key_name_admin(user)] pumped a random event.")) BLACKBOX_LOG_ADMIN_VERB("Pump Random Event") - log_admin("[key_name(src)] pumped a random event.") - -/client/proc/start_line_profiling() - set category = "Profile" - set name = "Start Line Profiling" - set desc = "Starts tracking line by line profiling for code lines that support it" + log_admin("[key_name(user)] pumped a random event.") +ADMIN_VERB_VISIBILITY(start_line_profiling, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(start_line_profiling, R_DEBUG, "Start Line Profiling", "Starts tracking line by line profiling for code lines that support it.", ADMIN_CATEGORY_PROFILE) LINE_PROFILE_START - message_admins(span_adminnotice("[key_name_admin(src)] started line by line profiling.")) + message_admins(span_adminnotice("[key_name_admin(user)] started line by line profiling.")) BLACKBOX_LOG_ADMIN_VERB("Start Line Profiling") - log_admin("[key_name(src)] started line by line profiling.") - -/client/proc/stop_line_profiling() - set category = "Profile" - set name = "Stops Line Profiling" - set desc = "Stops tracking line by line profiling for code lines that support it" + log_admin("[key_name(user)] started line by line profiling.") +ADMIN_VERB_VISIBILITY(stop_line_profiling, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(stop_line_profiling, R_DEBUG, "Stop Line Profiling", "Stops tracking line by line profiling for code lines that support it.", ADMIN_CATEGORY_PROFILE) LINE_PROFILE_STOP - message_admins(span_adminnotice("[key_name_admin(src)] stopped line by line profiling.")) + message_admins(span_adminnotice("[key_name_admin(user)] stopped line by line profiling.")) BLACKBOX_LOG_ADMIN_VERB("Stop Line Profiling") - log_admin("[key_name(src)] stopped line by line profiling.") - -/client/proc/show_line_profiling() - set category = "Profile" - set name = "Show Line Profiling" - set desc = "Shows tracked profiling info from code lines that support it" + log_admin("[key_name(user)] stopped line by line profiling.") +ADMIN_VERB_VISIBILITY(show_line_profiling, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(show_line_profiling, R_DEBUG, "Show Line Profiling", "Shows tracked profiling info from code lines that support it.", ADMIN_CATEGORY_PROFILE) var/sortlist = list( "Avg time" = GLOBAL_PROC_REF(cmp_profile_avg_time_dsc), "Total Time" = GLOBAL_PROC_REF(cmp_profile_time_dsc), "Call Count" = GLOBAL_PROC_REF(cmp_profile_count_dsc) ) - var/sort = input(src, "Sort type?", "Sort Type", "Avg time") as null|anything in sortlist + var/sort = input(user, "Sort type?", "Sort Type", "Avg time") as null|anything in sortlist if (!sort) return sort = sortlist[sort] - profile_show(src, sort) + profile_show(user, sort) -/client/proc/reload_configuration() - set category = "Debug" - set name = "Reload Configuration" - set desc = "Force config reload to world default" - if(!check_rights(R_DEBUG)) - return - if(tgui_alert(usr, "Are you absolutely sure you want to reload the configuration from the default path on the disk, wiping any in-round modifications?", "Really reset?", list("No", "Yes")) == "Yes") - config.admin_reload() - -/// A debug verb to check the sources of currently running timers -/client/proc/check_timer_sources() - set category = "Debug" - set name = "Check Timer Sources" - set desc = "Checks the sources of the running timers" - if (!check_rights(R_DEBUG)) +ADMIN_VERB(reload_configuration, R_DEBUG, "Reload Configuration", "Reloads the configuration from the default path on the disk, wiping any in-round modifications.", ADMIN_CATEGORY_DEBUG) + if(!tgui_alert(user, "Are you absolutely sure you want to reload the configuration from the default path on the disk, wiping any in-round modifications?", "Really reset?", list("No", "Yes")) == "Yes") return + config.admin_reload() +ADMIN_VERB(check_timer_sources, R_DEBUG, "Check Timer Sources", "Checks the sources of running timers.", ADMIN_CATEGORY_DEBUG) var/bucket_list_output = generate_timer_source_output(SStimer.bucket_list) var/second_queue = generate_timer_source_output(SStimer.second_queue) - usr << browse({" + user << browse({"

    bucket_list

    [bucket_list_output] @@ -889,24 +732,16 @@ [second_queue] "}, "window=check_timer_sources;size=700x700") -/// A debug verb to try and re-establish a connection with the TTS server and to refetch TTS voices. -/// Since voices are cached beforehand, this is unlikely to update preferences. -/client/proc/reestablish_tts_connection() - set category = "Debug" - set name = "Re-establish Connection To TTS" - set desc = "Re-establishes connection to the TTS server if possible" - if (!check_rights(R_DEBUG)) - return - - message_admins("[key_name_admin(usr)] attempted to re-establish connection to the TTS HTTP server.") - log_admin("[key_name(usr)] attempted to re-establish connection to the TTS HTTP server.") +ADMIN_VERB(reestablish_tts_connection, R_DEBUG, "Re-establish Connection To TTS", "Re-establishes connection to the TTS server if possible", ADMIN_CATEGORY_DEBUG) + message_admins("[key_name_admin(user)] attempted to re-establish connection to the TTS HTTP server.") + log_admin("[key_name(user)] attempted to re-establish connection to the TTS HTTP server.") var/success = SStts.establish_connection_to_tts() if(!success) - message_admins("[key_name_admin(usr)] failed to re-established the connection to the TTS HTTP server.") - log_admin("[key_name(usr)] failed to re-established the connection to the TTS HTTP server.") + message_admins("[key_name_admin(user)] failed to re-established the connection to the TTS HTTP server.") + log_admin("[key_name(user)] failed to re-established the connection to the TTS HTTP server.") return - message_admins("[key_name_admin(usr)] successfully re-established the connection to the TTS HTTP server.") - log_admin("[key_name(usr)] successfully re-established the connection to the TTS HTTP server.") + message_admins("[key_name_admin(user)] successfully re-established the connection to the TTS HTTP server.") + log_admin("[key_name(user)] successfully re-established the connection to the TTS HTTP server.") /proc/generate_timer_source_output(list/datum/timedevent/events) var/list/per_source = list() @@ -950,10 +785,14 @@ return b["count"] - a["count"] #ifdef TESTING -/client/proc/check_missing_sprites() - set category = "Debug" - set name = "Debug Worn Item Sprites" - set desc = "We're cancelling the Spritemageddon. (This will create a LOT of runtimes! Don't use on a live server!)" +ADMIN_VERB_CUSTOM_EXIST_CHECK(check_missing_sprites) + return TRUE +#else +ADMIN_VERB_CUSTOM_EXIST_CHECK(check_missing_sprites) + return FALSE +#endif + +ADMIN_VERB(check_missing_sprites, R_DEBUG, "Debug Worn Item Sprites", "We're cancelling the Spritemageddon. (This will create a LOT of runtimes! Don't use on a live server!)", ADMIN_CATEGORY_DEBUG) var/actual_file_name for(var/test_obj in subtypesof(/obj/item)) var/obj/item/sprite = new test_obj @@ -962,55 +801,54 @@ //Is there an explicit worn_icon to pick against the worn_icon_state? Easy street expected behavior. if(sprite.worn_icon) if(!(sprite.icon_state in icon_states(sprite.worn_icon))) - to_chat(src, span_warning("ERROR sprites for [sprite.type]. Slot Flags are [sprite.slot_flags]."), confidential = TRUE) + to_chat(user, span_warning("ERROR sprites for [sprite.type]. Slot Flags are [sprite.slot_flags]."), confidential = TRUE) else if(sprite.worn_icon_state) if(sprite.slot_flags & ITEM_SLOT_MASK) actual_file_name = 'icons/mob/clothing/mask.dmi' if(!(sprite.worn_icon_state in icon_states(actual_file_name))) - to_chat(src, span_warning("ERROR sprites for [sprite.type]. Mask slot."), confidential = TRUE) + to_chat(user, span_warning("ERROR sprites for [sprite.type]. Mask slot."), confidential = TRUE) if(sprite.slot_flags & ITEM_SLOT_NECK) actual_file_name = 'icons/mob/clothing/neck.dmi' if(!(sprite.worn_icon_state in icon_states(actual_file_name))) - to_chat(src, span_warning("ERROR sprites for [sprite.type]. Neck slot."), confidential = TRUE) + to_chat(user, span_warning("ERROR sprites for [sprite.type]. Neck slot."), confidential = TRUE) if(sprite.slot_flags & ITEM_SLOT_BACK) actual_file_name = 'icons/mob/clothing/back.dmi' if(!(sprite.worn_icon_state in icon_states(actual_file_name))) - to_chat(src, span_warning("ERROR sprites for [sprite.type]. Back slot."), confidential = TRUE) + to_chat(user, span_warning("ERROR sprites for [sprite.type]. Back slot."), confidential = TRUE) if(sprite.slot_flags & ITEM_SLOT_HEAD) actual_file_name = 'icons/mob/clothing/head/default.dmi' if(!(sprite.worn_icon_state in icon_states(actual_file_name))) - to_chat(src, span_warning("ERROR sprites for [sprite.type]. Head slot."), confidential = TRUE) + to_chat(user, span_warning("ERROR sprites for [sprite.type]. Head slot."), confidential = TRUE) if(sprite.slot_flags & ITEM_SLOT_BELT) actual_file_name = 'icons/mob/clothing/belt.dmi' if(!(sprite.worn_icon_state in icon_states(actual_file_name))) - to_chat(src, span_warning("ERROR sprites for [sprite.type]. Belt slot."), confidential = TRUE) + to_chat(user, span_warning("ERROR sprites for [sprite.type]. Belt slot."), confidential = TRUE) if(sprite.slot_flags & ITEM_SLOT_SUITSTORE) actual_file_name = 'icons/mob/clothing/belt_mirror.dmi' if(!(sprite.worn_icon_state in icon_states(actual_file_name))) - to_chat(src, span_warning("ERROR sprites for [sprite.type]. Suit Storage slot."), confidential = TRUE) + to_chat(user, span_warning("ERROR sprites for [sprite.type]. Suit Storage slot."), confidential = TRUE) else if(sprite.icon_state) if(sprite.slot_flags & ITEM_SLOT_MASK) actual_file_name = 'icons/mob/clothing/mask.dmi' if(!(sprite.icon_state in icon_states(actual_file_name))) - to_chat(src, span_warning("ERROR sprites for [sprite.type]. Mask slot."), confidential = TRUE) + to_chat(user, span_warning("ERROR sprites for [sprite.type]. Mask slot."), confidential = TRUE) if(sprite.slot_flags & ITEM_SLOT_NECK) actual_file_name = 'icons/mob/clothing/neck.dmi' if(!(sprite.icon_state in icon_states(actual_file_name))) - to_chat(src, span_warning("ERROR sprites for [sprite.type]. Neck slot."), confidential = TRUE) + to_chat(user, span_warning("ERROR sprites for [sprite.type]. Neck slot."), confidential = TRUE) if(sprite.slot_flags & ITEM_SLOT_BACK) actual_file_name = 'icons/mob/clothing/back.dmi' if(!(sprite.icon_state in icon_states(actual_file_name))) - to_chat(src, span_warning("ERROR sprites for [sprite.type]. Back slot."), confidential = TRUE) + to_chat(user, span_warning("ERROR sprites for [sprite.type]. Back slot."), confidential = TRUE) if(sprite.slot_flags & ITEM_SLOT_HEAD) actual_file_name = 'icons/mob/clothing/head/default.dmi' if(!(sprite.icon_state in icon_states(actual_file_name))) - to_chat(src, span_warning("ERROR sprites for [sprite.type]. Head slot."), confidential = TRUE) + to_chat(user, span_warning("ERROR sprites for [sprite.type]. Head slot."), confidential = TRUE) if(sprite.slot_flags & ITEM_SLOT_BELT) actual_file_name = 'icons/mob/clothing/belt.dmi' if(!(sprite.icon_state in icon_states(actual_file_name))) - to_chat(src, span_warning("ERROR sprites for [sprite.type]. Belt slot."), confidential = TRUE) + to_chat(user, span_warning("ERROR sprites for [sprite.type]. Belt slot."), confidential = TRUE) if(sprite.slot_flags & ITEM_SLOT_SUITSTORE) actual_file_name = 'icons/mob/clothing/belt_mirror.dmi' if(!(sprite.icon_state in icon_states(actual_file_name))) - to_chat(src, span_warning("ERROR sprites for [sprite.type]. Suit Storage slot."), confidential = TRUE) -#endif + to_chat(user, span_warning("ERROR sprites for [sprite.type]. Suit Storage slot."), confidential = TRUE) diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm index a6a9a204b85..4575614bb94 100644 --- a/code/modules/admin/verbs/diagnostics.dm +++ b/code/modules/admin/verbs/diagnostics.dm @@ -1,15 +1,10 @@ -/client/proc/air_status(turf/target) - set category = "Debug" - set name = "Display Air Status" - - if(!isturf(target)) - return - atmos_scan(user=usr, target=target, silent=TRUE) +ADMIN_VERB_VISIBILITY(debug_air_status, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(debug_air_status, R_DEBUG, "Debug Air Status" , ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, turf/target in world) + atmos_scan(user.mob, target, silent = TRUE) BLACKBOX_LOG_ADMIN_VERB("Show Air Status") -/client/proc/fix_next_move() - set category = "Debug" - set name = "Unfreeze Everyone" +ADMIN_VERB_VISIBILITY(fix_next_move, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(fix_next_move, R_DEBUG, "Fix Next Move", "Unfreezes all frozen mobs.", ADMIN_CATEGORY_DEBUG) var/largest_move_time = 0 var/largest_click_time = 0 var/mob/largest_move_mob = null @@ -34,12 +29,9 @@ message_admins("[ADMIN_LOOKUPFLW(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [DisplayTimeText(largest_click_time)]!") message_admins("world.time = [world.time]") BLACKBOX_LOG_ADMIN_VERB("Unfreeze Everyone") - return - -/client/proc/radio_report() - set category = "Debug" - set name = "Radio report" +ADMIN_VERB_VISIBILITY(radio_report, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(radio_report, R_DEBUG, "Radio Report", "Shows a report of all radio devices and their filters.", ADMIN_CATEGORY_DEBUG) var/output = "Radio Report
    " for (var/fq in SSradio.frequencies) output += "Freq: [fq]
    " @@ -64,29 +56,21 @@ else output += "    [device]
    " - usr << browse(output,"window=radioreport") + user << browse(output,"window=radioreport") BLACKBOX_LOG_ADMIN_VERB("Show Radio Report") -/client/proc/reload_admins() - set name = "Reload Admins" - set category = "Admin" - - if(!src.holder) - return - - var/confirm = tgui_alert(usr, "Are you sure you want to reload all admins?", "Confirm", list("Yes", "No")) +ADMIN_VERB(reload_admins, R_NONE, "Reload Admins", "Reloads all admins from the database.", ADMIN_CATEGORY_MAIN) + var/confirm = tgui_alert(user, "Are you sure you want to reload all admins?", "Confirm", list("Yes", "No")) if(confirm != "Yes") return load_admins() BLACKBOX_LOG_ADMIN_VERB("Reload All Admins") - message_admins("[key_name_admin(usr)] manually reloaded admins") + message_admins("[key_name_admin(user)] manually reloaded admins") -/client/proc/toggle_cdn() - set name = "Toggle CDN" - set category = "Server" +ADMIN_VERB(toggle_cdn, R_SERVER|R_DEBUG, "Toggle CDN", "Toggles the CDN for the server.", ADMIN_CATEGORY_SERVER) var/static/admin_disabled_cdn_transport = null - if (alert(usr, "Are you sure you want to toggle the CDN asset transport?", "Confirm", "Yes", "No") != "Yes") + if (alert(user, "Are you sure you want to toggle the CDN asset transport?", "Confirm", "Yes", "No") != "Yes") return var/current_transport = CONFIG_GET(string/asset_transport) if (!current_transport || current_transport == "simple") @@ -94,17 +78,17 @@ CONFIG_SET(string/asset_transport, admin_disabled_cdn_transport) admin_disabled_cdn_transport = null SSassets.OnConfigLoad() - message_admins("[key_name_admin(usr)] re-enabled the CDN asset transport") - log_admin("[key_name(usr)] re-enabled the CDN asset transport") + message_admins("[key_name_admin(user)] re-enabled the CDN asset transport") + log_admin("[key_name(user)] re-enabled the CDN asset transport") else - to_chat(usr, span_adminnotice("The CDN is not enabled!")) - if (tgui_alert(usr, "The CDN asset transport is not enabled! If you having issues with assets you can also try disabling filename mutations.", "The CDN asset transport is not enabled!", list("Try disabling filename mutations", "Nevermind")) == "Try disabling filename mutations") + to_chat(user, span_adminnotice("The CDN is not enabled!")) + if (tgui_alert(user, "The CDN asset transport is not enabled! If you having issues with assets you can also try disabling filename mutations.", "The CDN asset transport is not enabled!", list("Try disabling filename mutations", "Nevermind")) == "Try disabling filename mutations") SSassets.transport.dont_mutate_filenames = !SSassets.transport.dont_mutate_filenames - message_admins("[key_name_admin(usr)] [(SSassets.transport.dont_mutate_filenames ? "disabled" : "re-enabled")] asset filename transforms") - log_admin("[key_name(usr)] [(SSassets.transport.dont_mutate_filenames ? "disabled" : "re-enabled")] asset filename transforms") + message_admins("[key_name_admin(user)] [(SSassets.transport.dont_mutate_filenames ? "disabled" : "re-enabled")] asset filename transforms") + log_admin("[key_name(user)] [(SSassets.transport.dont_mutate_filenames ? "disabled" : "re-enabled")] asset filename transforms") else admin_disabled_cdn_transport = current_transport CONFIG_SET(string/asset_transport, "simple") SSassets.OnConfigLoad() - message_admins("[key_name_admin(usr)] disabled the CDN asset transport") - log_admin("[key_name(usr)] disabled the CDN asset transport") + message_admins("[key_name_admin(user)] disabled the CDN asset transport") + log_admin("[key_name(user)] disabled the CDN asset transport") diff --git a/code/modules/admin/verbs/ert.dm b/code/modules/admin/verbs/ert.dm index c99e226d310..1695a993bd5 100644 --- a/code/modules/admin/verbs/ert.dm +++ b/code/modules/admin/verbs/ert.dm @@ -269,18 +269,14 @@ return -/client/proc/summon_ert() - set category = "Admin.Fun" - set name = "Summon ERT" - set desc = "Summons an emergency response team" - - message_admins("[key_name(usr)] is creating a CentCom response team...") - if(holder?.makeEmergencyresponseteam()) - message_admins("[key_name(usr)] created a CentCom response team.") - log_admin("[key_name(usr)] created a CentCom response team.") +ADMIN_VERB(summon_ert, R_FUN, "Summon ERT", "Summons an emergency response team.", ADMIN_CATEGORY_FUN) + message_admins("[key_name_admin(user)] is creating a CentCom response team...") + if(user.holder?.makeEmergencyresponseteam()) + message_admins("[key_name_admin(user)] created a CentCom response team.") + log_admin("[key_name(user)] created a CentCom response team.") else - message_admins("[key_name_admin(usr)] tried to create a CentCom response team. Unfortunately, there were not enough candidates available.") - log_admin("[key_name(usr)] failed to create a CentCom response team.") + message_admins("[key_name_admin(user)] tried to create a CentCom response team. Unfortunately, there were not enough candidates available.") + log_admin("[key_name(user)] failed to create a CentCom response team.") #undef ERT_EXPERIENCED_LEADER_CHOOSE_TOP #undef DUMMY_HUMAN_SLOT_ADMIN diff --git a/code/modules/admin/verbs/fix_air.dm b/code/modules/admin/verbs/fix_air.dm index fb4a342c3d4..0f67200f61b 100644 --- a/code/modules/admin/verbs/fix_air.dm +++ b/code/modules/admin/verbs/fix_air.dm @@ -1,23 +1,16 @@ // Proc taken from yogstation, credit to nichlas0010 for the original -/client/proc/fix_air(turf/open/T in world) - set name = "Fix Air" - set category = "Admin.Game" - set desc = "Fixes air in specified radius." +ADMIN_VERB_AND_CONTEXT_MENU(fix_air, R_ADMIN, "Fix Air", "Fixes air in a specified radius.", ADMIN_CATEGORY_GAME, turf/open/locale in world, range = 2 as num) + message_admins("[key_name_admin(user)] fixed air with range [range] in area [locale.loc.name]") + user.mob.log_message("fixed air with range [range] in area [locale.loc.name]", LOG_ADMIN) - if(!holder) - to_chat(src, "Only administrators may use this command.", confidential = TRUE) - return - if(check_rights(R_ADMIN,1)) - var/range=input("Enter range:","Num",2) as num - message_admins("[key_name_admin(usr)] fixed air with range [range] in area [T.loc.name]") - usr.log_message("fixed air with range [range] in area [T.loc.name]", LOG_ADMIN) - for(var/turf/open/F in range(range,T)) - if(F.blocks_air) - //skip walls - continue - var/datum/gas_mixture/GM = SSair.parse_gas_string(F.initial_gas_mix, /datum/gas_mixture/turf) - F.copy_air(GM) - F.update_visuals() - - if(F.pollution) //SKYRAT EDIT ADDITION - qdel(F.pollution) + for(var/turf/open/valid_range_turf in range(range,locale)) + if(valid_range_turf.blocks_air) + //skip walls + continue + //SKYRAT EDIT ADDITION START + if(valid_range_turf.pollution) + qdel(valid_range_turf.pollution) + //SKYRAT EDIT ADDITION END + var/datum/gas_mixture/GM = SSair.parse_gas_string(valid_range_turf.initial_gas_mix, /datum/gas_mixture/turf) + valid_range_turf.copy_air(GM) + valid_range_turf.update_visuals() diff --git a/code/modules/admin/verbs/fov.dm b/code/modules/admin/verbs/fov.dm index f74ba6f8058..afcd379e4a0 100644 --- a/code/modules/admin/verbs/fov.dm +++ b/code/modules/admin/verbs/fov.dm @@ -1,14 +1,8 @@ -/client/proc/cmd_admin_toggle_fov() - set name = "Enable/Disable Field of View" - set category = "Debug" - - if(!check_rights(R_ADMIN) || !check_rights(R_DEBUG)) - return - +ADMIN_VERB(toggle_fov, R_ADMIN|R_DEBUG, "Enable/Disable Field Of View", "Toggle FOV globally.", ADMIN_CATEGORY_DEBUG) var/on_off = CONFIG_GET(flag/native_fov) - message_admins("[key_name_admin(usr)] has [on_off ? "disabled" : "enabled"] the Native Field of View configuration..") - log_admin("[key_name(usr)] has [on_off ? "disabled" : "enabled"] the Native Field of View configuration.") + message_admins("[key_name_admin(user)] has [on_off ? "disabled" : "enabled"] the Native Field of View configuration..") + log_admin("[key_name(user)] has [on_off ? "disabled" : "enabled"] the Native Field of View configuration.") CONFIG_SET(flag/native_fov, !on_off) SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggled Field of View", "[on_off ? "Enabled" : "Disabled"]")) diff --git a/code/modules/admin/verbs/fps.dm b/code/modules/admin/verbs/fps.dm index 578a0c09514..7af7968cde4 100644 --- a/code/modules/admin/verbs/fps.dm +++ b/code/modules/admin/verbs/fps.dm @@ -1,23 +1,16 @@ -//replaces the old Ticklag verb, fps is easier to understand -/client/proc/set_server_fps() - set category = "Debug" - set name = "Set Server FPS" - set desc = "Sets game speed in frames-per-second. Can potentially break the game" - - if(!check_rights(R_DEBUG)) - return - +ADMIN_VERB_VISIBILITY(set_server_fps, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(set_server_fps, R_DEBUG, "Set Server FPS", "Sets game speed in frames-per-second. Can potentially break the game", ADMIN_CATEGORY_DEBUG) var/cfg_fps = CONFIG_GET(number/fps) - var/new_fps = round(input("Sets game frames-per-second. Can potentially break the game (default: [cfg_fps])","FPS", world.fps) as num|null) + var/new_fps = round(input(user, "Sets game frames-per-second. Can potentially break the game (default: [cfg_fps])","FPS", world.fps) as num|null) if(new_fps <= 0) - to_chat(src, span_danger("Error: set_server_fps(): Invalid world.fps value. No changes made."), confidential = TRUE) + to_chat(user, span_danger("Error: set_server_fps(): Invalid world.fps value. No changes made."), confidential = TRUE) return if(new_fps > cfg_fps * 1.5) - if(tgui_alert(usr, "You are setting fps to a high value:\n\t[new_fps] frames-per-second\n\tconfig.fps = [cfg_fps]","Warning!",list("Confirm","ABORT-ABORT-ABORT")) != "Confirm") + if(tgui_alert(user, "You are setting fps to a high value:\n\t[new_fps] frames-per-second\n\tconfig.fps = [cfg_fps]","Warning!",list("Confirm","ABORT-ABORT-ABORT")) != "Confirm") return - var/msg = "[key_name(src)] has modified world.fps to [new_fps]" + var/msg = "[key_name(user)] has modified world.fps to [new_fps]" log_admin(msg, 0) message_admins(msg, 0) SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Set Server FPS", "[new_fps]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/getlogs.dm b/code/modules/admin/verbs/getlogs.dm index 77b43f9b49f..bceac01cbe0 100644 --- a/code/modules/admin/verbs/getlogs.dm +++ b/code/modules/admin/verbs/getlogs.dm @@ -1,17 +1,8 @@ -//This proc allows download of past server logs saved within the data/logs/ folder. -/client/proc/getserverlogs() - set name = "Get Server Logs" - set desc = "View/retrieve logfiles." - set category = "Admin" +ADMIN_VERB(get_server_logs, R_ADMIN, "Get Server Logs", "View or retrieve logfiles.", ADMIN_CATEGORY_MAIN) + user.browseserverlogs() - browseserverlogs() - -/client/proc/getcurrentlogs() - set name = "Get Current Logs" - set desc = "View/retrieve logfiles for the current round." - set category = "Admin" - - browseserverlogs(current=TRUE) +ADMIN_VERB(get_current_logs, R_ADMIN, "Get Current Logs", "View or retrieve logfiles for the current round.", ADMIN_CATEGORY_MAIN) + user.browseserverlogs(current=TRUE) /client/proc/browseserverlogs(current=FALSE) var/path = browse_files(current ? BROWSE_ROOT_CURRENT_LOGS : BROWSE_ROOT_ALL_LOGS) @@ -32,4 +23,3 @@ else return to_chat(src, "Attempting to send [path], this may take a fair few minutes if the file is very large.", confidential = TRUE) - return diff --git a/code/modules/admin/verbs/ghost_pool_protection.dm b/code/modules/admin/verbs/ghost_pool_protection.dm index 843f6868e70..439f4a37b89 100644 --- a/code/modules/admin/verbs/ghost_pool_protection.dm +++ b/code/modules/admin/verbs/ghost_pool_protection.dm @@ -1,11 +1,8 @@ //very similar to centcom_podlauncher in terms of how this is coded, so i kept a lot of comments from it -/client/proc/ghost_pool_protection() //Creates a verb for admins to open up the ui - set name = "Ghost Pool Protection" - set desc = "Choose which ways people can get into the round, or just clear it out completely for admin events." - set category = "Admin.Events" - var/datum/ghost_pool_menu/tgui = new(usr)//create the datum - tgui.ui_interact(usr)//datum has a tgui component, here we open the window +ADMIN_VERB(ghost_pool_protection, R_ADMIN, "Ghost Pool Protection", "Choose which ways people can get into the round, or just clear it out completely for admin events.", ADMIN_CATEGORY_EVENTS) + var/datum/ghost_pool_menu/tgui = new(user) + tgui.ui_interact(user.mob) /datum/ghost_pool_menu var/client/holder //client of whoever is using this datum diff --git a/code/modules/admin/verbs/lawpanel.dm b/code/modules/admin/verbs/lawpanel.dm index 9b52c8d7339..f1daaf17576 100644 --- a/code/modules/admin/verbs/lawpanel.dm +++ b/code/modules/admin/verbs/lawpanel.dm @@ -1,15 +1,9 @@ -/client/proc/cmd_admin_law_panel() - set category = "Admin.Events" - set name = "Law Panel" - - if(!check_rights(R_ADMIN)) - return - if(!isobserver(usr) && SSticker.HasRoundStarted()) - message_admins("[key_name_admin(usr)] checked AI laws via the Law Panel.") - +ADMIN_VERB(law_panel, R_ADMIN, "Law Panel", "View the AI laws.", ADMIN_CATEGORY_EVENTS) + if(!isobserver(user) && SSticker.HasRoundStarted()) + message_admins("[key_name_admin(user)] checked AI laws via the Law Panel.") + var/datum/law_panel/tgui = new + tgui.ui_interact(user.mob) BLACKBOX_LOG_ADMIN_VERB("Law Panel") - var/datum/law_panel/tgui = new() - tgui.ui_interact(usr) /datum/law_panel @@ -211,7 +205,7 @@ switch(action) if("lawchange_logs") - usr.client?.list_law_changes() + ui.user?.client?.holder?.list_law_changes() return FALSE if("force_state_laws") diff --git a/code/modules/admin/verbs/lua/lua_editor.dm b/code/modules/admin/verbs/lua/lua_editor.dm index 9e1b851824b..d4a4bc2ee50 100644 --- a/code/modules/admin/verbs/lua/lua_editor.dm +++ b/code/modules/admin/verbs/lua/lua_editor.dm @@ -233,10 +233,6 @@ . = ..() qdel(src) -/client/proc/open_lua_editor() - set name = "Open Lua Editor" - set category = "Debug" - if(!check_rights_for(src, R_DEBUG)) - return - var/datum/lua_editor/editor = new() - editor.ui_interact(usr) +ADMIN_VERB(lua_editor, R_DEBUG, "Open Lua Editor", "Its codin' time.", ADMIN_CATEGORY_DEBUG) + var/datum/lua_editor/editor = new + editor.ui_interact(user.mob) diff --git a/code/modules/admin/verbs/machine_upgrade.dm b/code/modules/admin/verbs/machine_upgrade.dm index 2f681574d5d..258de6bcf4d 100644 --- a/code/modules/admin/verbs/machine_upgrade.dm +++ b/code/modules/admin/verbs/machine_upgrade.dm @@ -1,13 +1,7 @@ -/proc/machine_upgrade(obj/machinery/M in world) - set name = "Tweak Component Ratings" - set category = "Debug" - if (!istype(M)) - return - - var/new_rating = input("Enter new rating:","Num") as num|null - if(new_rating && M.component_parts) - for(var/obj/item/stock_parts/P in M.component_parts) +ADMIN_VERB(machine_upgrade, R_DEBUG, "Tweak Component Ratings", ADMIN_VERB_NO_DESCRIPTION, ADMIN_CATEGORY_HIDDEN, obj/machinery/machine in world) + var/new_rating = input(user, "Enter new rating:","Num") as num|null + if(new_rating && machine.component_parts) + for(var/obj/item/stock_parts/P in machine.component_parts) P.rating = new_rating - M.RefreshParts() - + machine.RefreshParts() SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Machine Upgrade", "[new_rating]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/manipulate_organs.dm b/code/modules/admin/verbs/manipulate_organs.dm index 30f198bfba9..bfb5050dafa 100644 --- a/code/modules/admin/verbs/manipulate_organs.dm +++ b/code/modules/admin/verbs/manipulate_organs.dm @@ -1,7 +1,6 @@ -/client/proc/manipulate_organs(mob/living/carbon/carbon_victim in world) - set name = "Manipulate Organs" - set category = "Debug" - var/operation = tgui_input_list(usr, "Select organ operation", "Organ Manipulation", list("add organ", "add implant", "drop organ/implant", "remove organ/implant")) +ADMIN_VERB_VISIBILITY(manipulate_organs, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(manipulate_organs, R_DEBUG, "Manipulate Organs", "Manipulate the organs of a living carbon.", ADMIN_CATEGORY_DEBUG, mob/living/carbon/carbon_victim in world) + var/operation = tgui_input_list(user, "Select organ operation", "Organ Manipulation", list("add organ", "add implant", "drop organ/implant", "remove organ/implant")) if (isnull(operation)) return @@ -12,7 +11,7 @@ var/dat = replacetext("[path]", "/obj/item/organ/", ":") organs[dat] = path - var/obj/item/organ/organ_to_grant = tgui_input_list(usr, "Select organ type", "Organ Manipulation", organs) + var/obj/item/organ/organ_to_grant = tgui_input_list(user, "Select organ type", "Organ Manipulation", organs) if(isnull(organ_to_grant)) return if(isnull(organs[organ_to_grant])) @@ -20,18 +19,18 @@ organ_to_grant = organs[organ_to_grant] organ_to_grant = new organ_to_grant if(!organ_to_grant.Insert(carbon_victim)) - to_chat(usr, span_notice("[carbon_victim] is unable to carry this organ!")) + to_chat(user, span_notice("[carbon_victim] is unable to carry this organ!")) qdel(organ_to_grant) return - log_admin("[key_name(usr)] has added organ [organ_to_grant.type] to [key_name(carbon_victim)]") - message_admins("[key_name_admin(usr)] has added organ [organ_to_grant.type] to [ADMIN_LOOKUPFLW(carbon_victim)]") + log_admin("[key_name(user)] has added organ [organ_to_grant.type] to [key_name(carbon_victim)]") + message_admins("[key_name_admin(user)] has added organ [organ_to_grant.type] to [ADMIN_LOOKUPFLW(carbon_victim)]") if("add implant") for(var/path in subtypesof(/obj/item/implant)) var/dat = replacetext("[path]", "/obj/item/implant/", ":") organs[dat] = path - var/obj/item/implant/implant_to_grant = tgui_input_list(usr, "Select implant type", "Organ Manipulation", organs) + var/obj/item/implant/implant_to_grant = tgui_input_list(user, "Select implant type", "Organ Manipulation", organs) if(isnull(implant_to_grant)) return if(isnull(organs[implant_to_grant])) @@ -39,11 +38,11 @@ implant_to_grant = organs[implant_to_grant] implant_to_grant = new implant_to_grant if(!implant_to_grant.implant(carbon_victim)) - to_chat(usr, span_notice("[carbon_victim] is unable to hold this implant!")) + to_chat(user, span_notice("[carbon_victim] is unable to hold this implant!")) qdel(implant_to_grant) return - log_admin("[key_name(usr)] has added implant [implant_to_grant.type] to [key_name(carbon_victim)]") - message_admins("[key_name_admin(usr)] has added implant [implant_to_grant.type] to [ADMIN_LOOKUPFLW(carbon_victim)]") + log_admin("[key_name(user)] has added implant [implant_to_grant.type] to [key_name(carbon_victim)]") + message_admins("[key_name_admin(user)] has added implant [implant_to_grant.type] to [ADMIN_LOOKUPFLW(carbon_victim)]") if("drop organ/implant", "remove organ/implant") for(var/obj/item/organ/user_organs as anything in carbon_victim.organs) @@ -52,15 +51,15 @@ for(var/obj/item/implant/user_implants as anything in carbon_victim.implants) organs["[user_implants.name] ([user_implants.type])"] = user_implants - var/obj/item/organ_to_modify = tgui_input_list(usr, "Select organ/implant", "Organ Manipulation", organs) + var/obj/item/organ_to_modify = tgui_input_list(user, "Select organ/implant", "Organ Manipulation", organs) if(isnull(organ_to_modify)) return if(isnull(organs[organ_to_modify])) return organ_to_modify = organs[organ_to_modify] - log_admin("[key_name(usr)] has removed [organ_to_modify.type] from [key_name(carbon_victim)]") - message_admins("[key_name_admin(usr)] has removed [organ_to_modify.type] from [ADMIN_LOOKUPFLW(carbon_victim)]") + log_admin("[key_name(user)] has removed [organ_to_modify.type] from [key_name(carbon_victim)]") + message_admins("[key_name_admin(user)] has removed [organ_to_modify.type] from [ADMIN_LOOKUPFLW(carbon_victim)]") var/obj/item/organ/organ_holder var/obj/item/implant/implant_holder diff --git a/code/modules/admin/verbs/map_export.dm b/code/modules/admin/verbs/map_export.dm index 8233ce4389d..056a2ea1f8a 100644 --- a/code/modules/admin/verbs/map_export.dm +++ b/code/modules/admin/verbs/map_export.dm @@ -1,23 +1,22 @@ -/client/proc/map_export() - set category = "Debug" - set name = "Map Export" - set desc = "Select a part of the map by coordinates and download it." - - var/z_level = tgui_input_number(usr, "Export Which Z-Level?", "Map Exporter", usr.z || 2) - var/start_x = tgui_input_number(usr, "Start X?", "Map Exporter", usr.x || 1, world.maxx, 1) - var/start_y = tgui_input_number(usr, "Start Y?", "Map Exporter", usr.y || 1, world.maxy, 1) - var/end_x = tgui_input_number(usr, "End X?", "Map Exporter", usr.x || 1, world.maxx, 1) - var/end_y = tgui_input_number(usr, "End Y?", "Map Exporter", usr.y || 1, world.maxy, 1) +ADMIN_VERB(map_export, R_DEBUG, "Map Export", "Select a part of the map by coordinates and download it.", ADMIN_CATEGORY_DEBUG) + var/user_x = user.mob.x + var/user_y = user.mob.y + var/user_z = user.mob.z + var/z_level = tgui_input_number(user, "Export Which Z-Level?", "Map Exporter", user_z || 2) + var/start_x = tgui_input_number(user, "Start X?", "Map Exporter", user_x || 1, world.maxx, 1) + var/start_y = tgui_input_number(user, "Start Y?", "Map Exporter", user_y || 1, world.maxy, 1) + var/end_x = tgui_input_number(user, "End X?", "Map Exporter", user_x || 1, world.maxx, 1) + var/end_y = tgui_input_number(user, "End Y?", "Map Exporter", user_y || 1, world.maxy, 1) var/date = time2text(world.timeofday, "YYYY-MM-DD_hh-mm-ss") - var/file_name = sanitize_filename(tgui_input_text(usr, "Filename?", "Map Exporter", "exported_map_[date]")) - var/confirm = tgui_alert(usr, "Are you sure you want to do this? This will cause extreme lag!", "Map Exporter", list("Yes", "No")) + var/file_name = sanitize_filename(tgui_input_text(user, "Filename?", "Map Exporter", "exported_map_[date]")) + var/confirm = tgui_alert(user, "Are you sure you want to do this? This will cause extreme lag!", "Map Exporter", list("Yes", "No")) - if(confirm != "Yes" || !check_rights(R_DEBUG)) + if(confirm != "Yes") return var/map_text = write_map(start_x, start_y, z_level, end_x, end_y, z_level) - log_admin("Build Mode: [key_name(usr)] is exporting the map area from ([start_x], [start_y], [z_level]) through ([end_x], [end_y], [z_level])") - send_exported_map(usr, file_name, map_text) + log_admin("Build Mode: [key_name(user)] is exporting the map area from ([start_x], [start_y], [z_level]) through ([end_x], [end_y], [z_level])") + send_exported_map(user, file_name, map_text) /** * A procedure for saving DMM text to a file and then sending it to the user. diff --git a/code/modules/admin/verbs/map_template_loadverb.dm b/code/modules/admin/verbs/map_template_loadverb.dm index 827bbfb16e8..a27aca0f014 100644 --- a/code/modules/admin/verbs/map_template_loadverb.dm +++ b/code/modules/admin/verbs/map_template_loadverb.dm @@ -1,20 +1,17 @@ -/client/proc/map_template_load() - set category = "Debug" - set name = "Map template - Place" - +ADMIN_VERB(map_template_load, R_DEBUG, "Map Template - Place", "Place a map template at your current location.", ADMIN_CATEGORY_DEBUG) var/datum/map_template/template - var/map = tgui_input_list(usr, "Choose a Map Template to place at your CURRENT LOCATION","Place Map Template", sort_list(SSmapping.map_templates)) + var/map = tgui_input_list(user, "Choose a Map Template to place at your CURRENT LOCATION","Place Map Template", sort_list(SSmapping.map_templates)) if(!map) return template = SSmapping.map_templates[map] - var/turf/T = get_turf(mob) + var/turf/T = get_turf(user.mob) if(!T) return var/list/preview = list() var/center - var/centeralert = tgui_alert(usr,"Center Template.","Template Centering",list("Yes","No")) + var/centeralert = tgui_alert(user,"Center Template.","Template Centering",list("Yes","No")) switch(centeralert) if("Yes") center = TRUE @@ -26,8 +23,8 @@ var/image/item = image('icons/turf/overlays.dmi', place_on,"greenOverlay") SET_PLANE(item, ABOVE_LIGHTING_PLANE, place_on) preview += item - images += preview - if(tgui_alert(usr,"Confirm location.","Template Confirm",list("Yes","No")) == "Yes") + user.images += preview + if(tgui_alert(user,"Confirm location.","Template Confirm",list("Yes","No")) == "Yes") if(template.load(T, centered = center)) var/affected = template.get_affected_turfs(T, centered = center) for(var/AT in affected) @@ -36,23 +33,20 @@ template.post_load(P) break - message_admins(span_adminnotice("[key_name_admin(src)] has placed a map template ([template.name]) at [ADMIN_COORDJMP(T)]")) + message_admins(span_adminnotice("[key_name_admin(user)] has placed a map template ([template.name]) at [ADMIN_COORDJMP(T)]")) else - to_chat(src, "Failed to place map", confidential = TRUE) - images -= preview + to_chat(user, "Failed to place map", confidential = TRUE) + user.images -= preview -/client/proc/map_template_upload() - set category = "Debug" - set name = "Map Template - Upload" - - var/map = input(src, "Choose a Map Template to upload to template storage","Upload Map Template") as null|file +ADMIN_VERB(map_template_upload, R_DEBUG, "Map Template - Upload", "Upload a map template to the server.", ADMIN_CATEGORY_DEBUG) + var/map = input(user, "Choose a Map Template to upload to template storage","Upload Map Template") as null|file if(!map) return if(copytext("[map]", -4) != ".dmm")//4 == length(".dmm") - to_chat(src, span_warning("Filename must end in '.dmm': [map]"), confidential = TRUE) + to_chat(user, span_warning("Filename must end in '.dmm': [map]"), confidential = TRUE) return var/datum/map_template/M - switch(tgui_alert(usr, "What kind of map is this?", "Map type", list("Normal", "Shuttle", "Cancel"))) + switch(tgui_alert(user, "What kind of map is this?", "Map type", list("Normal", "Shuttle", "Cancel"))) if("Normal") M = new /datum/map_template(map, "[map]", TRUE) if("Shuttle") @@ -60,23 +54,23 @@ else return if(!M.cached_map) - to_chat(src, span_warning("Map template '[map]' failed to parse properly."), confidential = TRUE) + to_chat(user, span_warning("Map template '[map]' failed to parse properly."), confidential = TRUE) return var/datum/map_report/report = M.cached_map.check_for_errors() var/report_link if(report) - report.show_to(src) + report.show_to(user) report_link = " - validation report" - to_chat(src, span_warning("Map template '[map]' failed validation."), confidential = TRUE) + to_chat(user, span_warning("Map template '[map]' failed validation."), confidential = TRUE) if(report.loadable) - var/response = tgui_alert(usr, "The map failed validation, would you like to load it anyways?", "Map Errors", list("Cancel", "Upload Anyways")) + var/response = tgui_alert(user, "The map failed validation, would you like to load it anyways?", "Map Errors", list("Cancel", "Upload Anyways")) if(response != "Upload Anyways") return else - tgui_alert(usr, "The map failed validation and cannot be loaded.", "Map Errors", list("Oh Darn")) + tgui_alert(user, "The map failed validation and cannot be loaded.", "Map Errors", list("Oh Darn")) return SSmapping.map_templates[M.name] = M - message_admins(span_adminnotice("[key_name_admin(src)] has uploaded a map template '[map]' ([M.width]x[M.height])[report_link].")) - to_chat(src, span_notice("Map template '[map]' ready to place ([M.width]x[M.height])"), confidential = TRUE) + message_admins(span_adminnotice("[key_name_admin(user)] has uploaded a map template '[map]' ([M.width]x[M.height])[report_link].")) + to_chat(user, span_notice("Map template '[map]' ready to place ([M.width]x[M.height])"), confidential = TRUE) diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index 8f4206ca905..69dd533e097 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -1,69 +1,5 @@ -//- Are all the floors with or without air, as they should be? (regular or airless) -//- Does the area have an APC? -//- Does the area have an Air Alarm? -//- Does the area have a Request Console? -//- Does the area have lights? -//- Does the area have a light switch? -//- Does the area have enough intercoms? -//- Does the area have enough security cameras? (Use the 'Camera Range Display' verb under Debug) -//- Is the area connected to the scrubbers air loop? -//- Is the area connected to the vent air loop? (vent pumps) -//- Is everything wired properly? -//- Does the area have a fire alarm and firedoors? -//- Do all pod doors work properly? -//- Are accesses set properly on doors, pod buttons, etc. -//- Are all items placed properly? (not below vents, scrubbers, tables) -//- Does the disposal system work properly from all the disposal units in this room and all the units, the pipes of which pass through this room? -//- Check for any misplaced or stacked piece of pipe (air and disposal) -//- Check for any misplaced or stacked piece of wire -//- Identify how hard it is to break into the area and where the weak points are -//- Check if the area has too much empty space. If so, make it smaller and replace the rest with maintenance tunnels. - -GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list( - /client/proc/camera_view, //-errorage - /client/proc/sec_camera_report, //-errorage - /client/proc/intercom_view, //-errorage - /client/proc/air_status, //Air things - /client/proc/Cell, //More air things - /client/proc/atmosscan, //check plumbing - /client/proc/powerdebug, //check power - /client/proc/count_objects_on_z_level, - /client/proc/count_objects_all, - /client/proc/cmd_assume_direct_control, //-errorage - /client/proc/cmd_give_direct_control, - /client/proc/set_server_fps, //allows you to set the ticklag. - /client/proc/cmd_admin_grantfullaccess, - /client/proc/cmd_admin_areatest_all, - /client/proc/cmd_admin_areatest_station, - /client/proc/cmd_admin_areatest_station_no_maintenance, - #ifdef TESTING - /client/proc/see_dirty_varedits, - #endif - /client/proc/cmd_admin_rejuvenate, - /datum/admins/proc/show_traitor_panel, - /client/proc/disable_communication, - /client/proc/show_map_reports, - /client/proc/cmd_show_at_list, - /client/proc/cmd_show_at_markers, - /client/proc/manipulate_organs, - /client/proc/start_line_profiling, - /client/proc/stop_line_profiling, - /client/proc/show_line_profiling, - /client/proc/create_mapping_job_icons, - /client/proc/debug_z_levels, - /client/proc/place_ruin, - /client/proc/station_food_debug, - /client/proc/station_stack_debug, - /client/proc/check_for_obstructed_atmospherics, - /client/proc/modify_lights, - /client/proc/visualize_lights, -)) -GLOBAL_PROTECT(admin_verbs_debug_mapping) - -/client/proc/camera_view() - set category = "Mapping" - set name = "Camera Range Display" - +ADMIN_VERB_VISIBILITY(camera_view, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(camera_view, R_DEBUG, "Camera Range Display", "Shows the range of cameras on the station.", ADMIN_CATEGORY_MAPPING) var/on = FALSE for(var/turf/T in world) if(T.maptext) @@ -82,28 +18,20 @@ GLOBAL_PROTECT(admin_verbs_debug_mapping) #ifdef TESTING GLOBAL_LIST_EMPTY(dirty_vars) -/client/proc/see_dirty_varedits() - set category = "Mapping" - set name = "Dirty Varedits" - +ADMIN_VERB_VISIBILITY(see_dirty_varedits, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(see_dirty_varedits, R_DEBUG, "Dirty Varedits", "Shows all dirty varedits.", ADMIN_CATEGORY_MAPPING) var/list/dat = list() dat += "

    Abandon all hope ye who enter here



    " for(var/thing in GLOB.dirty_vars) dat += "[thing]
    " CHECK_TICK - var/datum/browser/popup = new(usr, "dirty_vars", "Dirty Varedits", 900, 750) + var/datum/browser/popup = new(user, "dirty_vars", "Dirty Varedits", 900, 750) popup.set_content(dat.Join()) popup.open() #endif -/client/proc/sec_camera_report() - set category = "Mapping" - set name = "Camera Report" - - if(!Master) - tgui_alert(usr,"Master_controller not found.","Sec Camera Report") - return FALSE - +ADMIN_VERB_VISIBILITY(sec_camera_report, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(sec_camera_report, R_DEBUG, "Camera Report", "Get a printout of all camera issues.", ADMIN_CATEGORY_MAPPING) var/list/obj/machinery/camera/CL = list() for(var/obj/machinery/camera/C as anything in GLOB.cameranet.cameras) @@ -133,15 +61,13 @@ GLOBAL_LIST_EMPTY(dirty_vars) output += "
  • Camera not connected to wall at [ADMIN_VERBOSEJMP(C1)] Network: [json_encode(C1.network)]
  • " output += "" - usr << browse(output,"window=airreport;size=1000x500") + user << browse(output,"window=airreport;size=1000x500") BLACKBOX_LOG_ADMIN_VERB("Show Camera Report") -/client/proc/intercom_view() - set category = "Mapping" - set name = "Intercom Range Display" - +ADMIN_VERB_VISIBILITY(intercom_view, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(intercom_view, R_DEBUG, "Intercom Range Display", "Shows the range of intercoms on the station.", ADMIN_CATEGORY_MAPPING) var/static/intercom_range_display_status = FALSE - intercom_range_display_status = !intercom_range_display_status //blame cyberboss if this breaks something //blamed + intercom_range_display_status = !intercom_range_display_status for(var/obj/effect/abstract/marker/intercom/marker in GLOB.all_abstract_markers) qdel(marker) @@ -153,23 +79,17 @@ GLOBAL_LIST_EMPTY(dirty_vars) new /obj/effect/abstract/marker/intercom(turf) BLACKBOX_LOG_ADMIN_VERB("Show Intercom Range") -/client/proc/show_map_reports() - set category = "Mapping" - set name = "Show map report list" - set desc = "Displays a list of map reports" - +ADMIN_VERB_VISIBILITY(show_map_reports, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(show_map_reports, R_DEBUG, "Show Map Reports", "Displays a list of map reports.", ADMIN_CATEGORY_MAPPING) var/dat = {"List of all map reports:
    "} for(var/datum/map_report/report as anything in GLOB.map_reports) dat += "[report.tag] ([report.original_path]) - View
    " - usr << browse(dat, "window=map_reports") - -/client/proc/cmd_show_at_list() - set category = "Mapping" - set name = "Show roundstart AT list" - set desc = "Displays a list of active turfs coordinates at roundstart" + user << browse(dat, "window=map_reports") +ADMIN_VERB_VISIBILITY(cmd_show_at_list, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(cmd_show_at_list, R_DEBUG, "Show roundstart AT list", "Displays a list of active turfs coordinates at roundstart.", ADMIN_CATEGORY_MAPPING) var/dat = {"Coordinate list of Active Turfs at Roundstart
    Real-time Active Turfs list you can see in Air Subsystem at active_turfs var
    "} @@ -178,50 +98,39 @@ GLOBAL_LIST_EMPTY(dirty_vars) dat += "[ADMIN_VERBOSEJMP(T)]\n" dat += "
    " - usr << browse(dat, "window=at_list") + user << browse(dat, "window=at_list") BLACKBOX_LOG_ADMIN_VERB("Show Roundstart Active Turfs") -/client/proc/cmd_show_at_markers() - set category = "Mapping" - set name = "Show roundstart AT markers" - set desc = "Places a marker on all active-at-roundstart turfs" - +ADMIN_VERB_VISIBILITY(cmd_show_at_markers, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(cmd_show_at_markers, R_DEBUG, "Show roundstart AT markers", "Places a marker on all active-at-roundstart turfs.", ADMIN_CATEGORY_MAPPING) var/count = 0 for(var/obj/effect/abstract/marker/at/AT in GLOB.all_abstract_markers) qdel(AT) count++ if(count) - to_chat(usr, "[count] AT markers removed.", confidential = TRUE) + to_chat(user, "[count] AT markers removed.", confidential = TRUE) else for(var/t in GLOB.active_turfs_startlist) new /obj/effect/abstract/marker/at(t) count++ - to_chat(usr, "[count] AT markers placed.", confidential = TRUE) + to_chat(user, "[count] AT markers placed.", confidential = TRUE) BLACKBOX_LOG_ADMIN_VERB("Show Roundstart Active Turf Markers") -/client/proc/enable_mapping_verbs() - set category = "Debug" - set name = "Mapping verbs - Enable" - if(!check_rights(R_DEBUG)) - return - remove_verb(src, /client/proc/enable_mapping_verbs) - add_verb(src, list(/client/proc/disable_mapping_verbs, GLOB.admin_verbs_debug_mapping)) +ADMIN_VERB(enable_mapping_verbs, R_DEBUG, "Enable Mapping Verbs", "Enable all mapping verbs.", ADMIN_CATEGORY_MAPPING) + SSadmin_verbs.update_visibility_flag(user, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG, TRUE) BLACKBOX_LOG_ADMIN_VERB("Enable Debug Verbs") -/client/proc/disable_mapping_verbs() - set category = "Debug" - set name = "Mapping verbs - Disable" - remove_verb(src, list(/client/proc/disable_mapping_verbs, GLOB.admin_verbs_debug_mapping)) - add_verb(src, /client/proc/enable_mapping_verbs) +ADMIN_VERB_VISIBILITY(disable_mapping_verbs, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(disable_mapping_verbs, R_DEBUG, "Disable Mapping Verbs", "Disable all mapping verbs.", ADMIN_CATEGORY_MAPPING) + SSadmin_verbs.update_visibility_flag(user, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG, FALSE) BLACKBOX_LOG_ADMIN_VERB("Disable Debug Verbs") -/client/proc/count_objects_on_z_level() - set category = "Mapping" - set name = "Count Objects On Level" - var/level = input("Which z-level?","Level?") as text|null +ADMIN_VERB_VISIBILITY(count_objects_on_z_level, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(count_objects_on_z_level, R_DEBUG, "Count Objects On Z-Level", "Counts the number of objects of a certain type on a specific z-level.", ADMIN_CATEGORY_MAPPING) + var/level = input(user, "Which z-level?","Level?") as text|null if(!level) return var/num_level = text2num(level) @@ -230,7 +139,7 @@ GLOBAL_LIST_EMPTY(dirty_vars) if(!isnum(num_level)) return - var/type_text = input("Which type path?","Path?") as text|null + var/type_text = input(user, "Which type path?","Path?") as text|null if(!type_text) return var/type_path = text2path(type_text) @@ -257,11 +166,9 @@ GLOBAL_LIST_EMPTY(dirty_vars) to_chat(world, "There are [count] objects of type [type_path] on z-level [num_level]", confidential = TRUE) BLACKBOX_LOG_ADMIN_VERB("Count Objects Zlevel") -/client/proc/count_objects_all() - set category = "Mapping" - set name = "Count Objects All" - - var/type_text = input("Which type path?","") as text|null +ADMIN_VERB_VISIBILITY(count_objects_all, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(count_objects_all, R_DEBUG, "Count Objects All", "Counts the number of objects of a certain type in the game world.", ADMIN_CATEGORY_MAPPING) + var/type_text = input(user, "Which type path?","") as text|null if(!type_text) return var/type_path = text2path(type_text) @@ -277,84 +184,51 @@ GLOBAL_LIST_EMPTY(dirty_vars) to_chat(world, "There are [count] objects of type [type_path] in the game world", confidential = TRUE) BLACKBOX_LOG_ADMIN_VERB("Count Objects All") - -//This proc is intended to detect lag problems relating to communication procs GLOBAL_VAR_INIT(say_disabled, FALSE) -/client/proc/disable_communication() - set category = "Mapping" - set name = "Disable all communication verbs" - +ADMIN_VERB_VISIBILITY(disable_communication, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(disable_communication, R_DEBUG, "Disable all communication verbs", "Disables all communication verbs.", ADMIN_CATEGORY_MAPPING) GLOB.say_disabled = !GLOB.say_disabled if(GLOB.say_disabled) - message_admins("[key] used 'Disable all communication verbs', killing all communication methods.") + message_admins("[key_name_admin(user)] used 'Disable all communication verbs', killing all communication methods.") else - message_admins("[key] used 'Disable all communication verbs', restoring all communication methods.") -/* SKYRAT EDIT: lol, lmao, fuck icon bugs from byond -//This generates the icon states for job starting location landmarks. -/client/proc/create_mapping_job_icons() - set name = "Generate job landmarks icons" - set category = "Mapping" + message_admins("[key_name_admin(user)] used 'Disable all communication verbs', restoring all communication methods.") + +ADMIN_VERB_VISIBILITY(create_mapping_job_icons, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(create_mapping_job_icons, R_DEBUG, "Generate job landmarks icons", "Generates job starting location landmarks.", ADMIN_CATEGORY_MAPPING) var/icon/final = icon() + var/list/job_key_to_icon = list() // SKYRAT EDIT ADDITION var/mob/living/carbon/human/dummy/D = new(locate(1,1,1)) //spawn on 1,1,1 so we don't have runtimes when items are deleted D.setDir(SOUTH) for(var/job in subtypesof(/datum/job)) var/datum/job/JB = new job switch(JB.title) if(JOB_AI) - final.Insert(icon('icons/mob/silicon/ai.dmi', "ai", SOUTH, 1), "AI") + job_key_to_icon["AI"] = icon('icons/mob/silicon/ai.dmi', "ai", SOUTH, 1) // SKYRAT EDIT CHANGE - ORIGINAL: final.Insert(icon('icons/mob/silicon/ai.dmi', "ai", SOUTH, 1), "AI") if(JOB_CYBORG) - final.Insert(icon('icons/mob/silicon/robots.dmi', "robot", SOUTH, 1), "Cyborg") + job_key_to_icon["Cyborg"] = icon('icons/mob/silicon/robots.dmi', "robot", SOUTH, 1) // SKYRAT EDIT CHANGE - ORIGINAL: final.Insert(icon('icons/mob/silicon/robots.dmi', "robot", SOUTH, 1), "Cyborg") else for(var/obj/item/I in D) qdel(I) randomize_human(D) - D.dress_up_as_job(JB, TRUE) - var/icon/I = icon(getFlatIcon(D), frame = 1) - final.Insert(I, JB.title) - qdel(D) - //Also add the x - for(var/x_number in 1 to 4) - final.Insert(icon('icons/hud/screen_gen.dmi', "x[x_number == 1 ? "" : x_number]"), "x[x_number == 1 ? "" : x_number]") - fcopy(final, "icons/mob/landmarks.dmi") -*/ -// SKYRAT EDIT BEGIN: THIS SHIT WAS BROKEN due to an issue with byond and how icons cache -//This generates the icon states for job starting location landmarks. -/client/proc/create_mapping_job_icons() - set name = "Generate job landmarks icons" - set category = "Mapping" - var/list/job_key_to_icon = list() - for(var/job in subtypesof(/datum/job)) - var/mob/living/carbon/human/dummy/D = new(locate(1,1,1)) //spawn on 1,1,1 so we don't have runtimes when items are deleted - D.setDir(SOUTH) - var/datum/job/JB = new job - to_chat(world, "Generating icon for job [JB.title]") - switch(JB.title) - if("AI") - job_key_to_icon["AI"] = icon('icons/mob/silicon/ai.dmi', "ai", SOUTH, 1) - if("Cyborg") - job_key_to_icon["Cyborg"] = icon('icons/mob/silicon/robots.dmi', "robot", SOUTH, 1) - else - randomize_human(D) + // SKYRAT EDIT CHANGE START - ORIGINAL: D.dress_up_as_job(JB, TRUE) if(JB.outfit) D.equipOutfit(JB.outfit, TRUE) + // SKYRAT EDIT CHANGE END var/icon/I = icon(getFlatIcon(D), frame = 1) - job_key_to_icon[JB.title] = I - qdel(D) - to_chat(world, "Done generating icons.") - var/icon/final = icon() + job_key_to_icon[JB.title] = I // SKYRAT EDIT CHANGE - ORIGINAL: final.Insert(I, JB.title) + qdel(D) + // SKYRAT EDIT ADDITION START for(var/job_key in job_key_to_icon) final.Insert(job_key_to_icon[job_key], job_key) + // SKYRAT EDIT ADDITION END //Also add the x for(var/x_number in 1 to 4) final.Insert(icon('icons/hud/screen_gen.dmi', "x[x_number == 1 ? "" : x_number]"), "x[x_number == 1 ? "" : x_number]") fcopy(final, "icons/mob/landmarks.dmi") - to_chat(world, "Done generating landmarks.dmi.") -// SKYRAT EDIT END -/client/proc/debug_z_levels() - set name = "Debug Z-Levels" - set category = "Mapping" - to_chat(src, examine_block(gather_z_level_information(append_grid = TRUE)), confidential = TRUE) +ADMIN_VERB_VISIBILITY(debug_z_levels, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(debug_z_levels, R_DEBUG, "Debug Z-Levels", "Displays a list of all z-levels and their linkages.", ADMIN_CATEGORY_MAPPING) + to_chat(user, examine_block(gather_z_level_information(append_grid = TRUE)), confidential = TRUE) /// Returns all necessary z-level information. Argument `append_grid` allows the user to see a table showing all of the z-level linkages, which is only visible and useful in-game. /proc/gather_z_level_information(append_grid = FALSE) @@ -416,9 +290,8 @@ GLOBAL_VAR_INIT(say_disabled, FALSE) return messages.Join("\n") -/client/proc/station_food_debug() - set name = "Count Station Food" - set category = "Mapping" +ADMIN_VERB_VISIBILITY(station_food_debug, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(station_food_debug, R_DEBUG, "Count Station Food", "Counts the number of food items on the station.", ADMIN_CATEGORY_MAPPING) var/list/foodcount = list() for(var/obj/item/food/fuck_me in world) var/turf/location = get_turf(fuck_me) @@ -435,13 +308,12 @@ GLOBAL_VAR_INIT(say_disabled, FALSE) var/page_style = "" var/page_contents = "[page_style][table_header][jointext(table_contents, "")]
    " - var/datum/browser/popup = new(mob, "fooddebug", "Station Food Count", 600, 400) + var/datum/browser/popup = new(user.mob, "fooddebug", "Station Food Count", 600, 400) popup.set_content(page_contents) popup.open() -/client/proc/station_stack_debug() - set name = "Count Station Stacks" - set category = "Mapping" +ADMIN_VERB_VISIBILITY(station_stack_debug, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(station_stack_debug, R_DEBUG, "Count Station Stacks", "Count the stacks of materials on station.", ADMIN_CATEGORY_MAPPING) var/list/stackcount = list() for(var/obj/item/stack/fuck_me in world) var/turf/location = get_turf(fuck_me) @@ -458,18 +330,13 @@ GLOBAL_VAR_INIT(say_disabled, FALSE) var/page_style = "" var/page_contents = "[page_style][table_header][jointext(table_contents, "")]
    " - var/datum/browser/popup = new(mob, "stackdebug", "Station Stack Count", 600, 400) + var/datum/browser/popup = new(user.mob, "stackdebug", "Station Stack Count", 600, 400) popup.set_content(page_contents) popup.open() -/// Check all tiles with a vent or scrubber on it and ensure that nothing is covering it up. -/client/proc/check_for_obstructed_atmospherics() - set name = "Check For Obstructed Atmospherics" - set category = "Mapping" - if(!holder) - to_chat(src, "Only administrators may use this command.", confidential = TRUE) - return - message_admins(span_adminnotice("[key_name_admin(usr)] is checking for obstructed atmospherics through the debug command.")) +ADMIN_VERB_VISIBILITY(check_for_obstructed_atmospherics, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(check_for_obstructed_atmospherics, R_DEBUG, "Check For Obstructed Atmospherics", "Checks for obstructions on atmospherics machines.", ADMIN_CATEGORY_MAPPING) + message_admins(span_adminnotice("[key_name_admin(user)] is checking for obstructed atmospherics through the debug command.")) BLACKBOX_LOG_ADMIN_VERB("Check For Obstructed Atmospherics") var/list/results = list() @@ -518,17 +385,14 @@ GLOBAL_VAR_INIT(say_disabled, FALSE) results += "There is an obstruction on top of an atmospherics machine at: [ADMIN_VERBOSEJMP(iterated_turf)].
    " if(results.len == 1) // only the header is in the list, we're good - to_chat(src, "No obstructions detected.", confidential = TRUE) + to_chat(user, "No obstructions detected.", confidential = TRUE) else - var/datum/browser/popup = new(usr, "atmospherics_obstructions", "Atmospherics Obstructions", 900, 750) + var/datum/browser/popup = new(user.mob, "atmospherics_obstructions", "Atmospherics Obstructions", 900, 750) popup.set_content(results.Join()) popup.open() -/client/proc/modify_lights() - set name = "Toggle Light Debug" - set category = "Mapping" - if(!check_rights(R_DEBUG)) - return +ADMIN_VERB_VISIBILITY(modify_lights, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(modify_lights, R_DEBUG, "Toggle Light Debug", "Toggles light debug mode.", ADMIN_CATEGORY_MAPPING) if(GLOB.light_debug_enabled) undebug_sources() return @@ -540,10 +404,6 @@ GLOBAL_VAR_INIT(say_disabled, FALSE) CHECK_TICK debug_sources() -/client/proc/visualize_lights() - set name = "Visualize Lighting Corners" - set category = "Mapping" - if(!check_rights(R_DEBUG)) - return - +ADMIN_VERB_VISIBILITY(visualize_lights, ADMIN_VERB_VISIBLITY_FLAG_MAPPING_DEBUG) +ADMIN_VERB(visualize_lights, R_DEBUG, "Visualize Lighting Corners", "Visualizes the corners of all lights on the station.", ADMIN_CATEGORY_MAPPING) display_corners() diff --git a/code/modules/admin/verbs/maprotation.dm b/code/modules/admin/verbs/maprotation.dm index c41677db37c..09d6d93bee6 100644 --- a/code/modules/admin/verbs/maprotation.dm +++ b/code/modules/admin/verbs/maprotation.dm @@ -1,16 +1,13 @@ -/client/proc/forcerandomrotate() - set category = "Server" - set name = "Trigger Random Map Rotation" - var/rotate = tgui_alert(usr,"Force a random map rotation to trigger?", "Rotate map?", list("Yes", "Cancel")) + +ADMIN_VERB(force_random_rotate, R_SERVER, "Trigger 'Random' Map Rotation", "Force a map vote.", ADMIN_CATEGORY_SERVER) + var/rotate = tgui_alert(user,"Force a random map rotation to trigger?", "Rotate map?", list("Yes", "Cancel")) if (rotate != "Yes") return - message_admins("[key_name_admin(usr)] is forcing a random map rotation.") - log_admin("[key_name(usr)] is forcing a random map rotation.") + message_admins("[key_name_admin(user)] is forcing a random map rotation.") + log_admin("[key_name(user)] is forcing a random map rotation.") SSmapping.maprotate() -/client/proc/adminchangemap() - set category = "Server" - set name = "Change Map" +ADMIN_VERB(admin_change_map, R_SERVER, "Change Map", "Set the next map.", ADMIN_CATEGORY_SERVER) var/list/maprotatechoices = list() for (var/map in config.maplist) var/datum/map_config/virtual_map = config.maplist[map] @@ -32,21 +29,21 @@ mapname += "\]" maprotatechoices[mapname] = virtual_map - var/chosenmap = tgui_input_list(usr, "Choose a map to change to", "Change Map", sort_list(maprotatechoices)|"Custom") + var/chosenmap = tgui_input_list(user, "Choose a map to change to", "Change Map", sort_list(maprotatechoices)|"Custom") if (isnull(chosenmap)) return if(chosenmap == "Custom") - message_admins("[key_name_admin(usr)] is changing the map to a custom map") - log_admin("[key_name(usr)] is changing the map to a custom map") + message_admins("[key_name_admin(user)] is changing the map to a custom map") + log_admin("[key_name(user)] is changing the map to a custom map") var/datum/map_config/virtual_map = new - var/map_file = input("Pick file:", "Map File") as null|file + var/map_file = input(user, "Pick file:", "Map File") as null|file if(isnull(map_file)) return if(copytext("[map_file]", -4) != ".dmm")//4 == length(".dmm") - to_chat(src, span_warning("Filename must end in '.dmm': [map_file]")) + to_chat(user, span_warning("Filename must end in '.dmm': [map_file]")) return if(fexists("_maps/custom/[map_file]")) @@ -56,20 +53,20 @@ // This is to make sure the map works so the server does not start without a map. var/datum/parsed_map/M = new (map_file) if(!M) - to_chat(src, span_warning("Map '[map_file]' failed to parse properly.")) + to_chat(user, span_warning("Map '[map_file]' failed to parse properly.")) return if(!M.bounds) - to_chat(src, span_warning("Map '[map_file]' has non-existant bounds.")) + to_chat(user, span_warning("Map '[map_file]' has non-existant bounds.")) qdel(M) return qdel(M) var/config_file = null var/list/json_value = list() - var/config = tgui_alert(usr,"Would you like to upload an additional config for this map?", "Map Config", list("Yes", "No")) + var/config = tgui_alert(user,"Would you like to upload an additional config for this map?", "Map Config", list("Yes", "No")) if(config == "Yes") - config_file = input("Pick file:", "Config JSON File") as null|file + config_file = input(user, "Pick file:", "Config JSON File") as null|file if(isnull(config_file)) return if(copytext("[config_file]", -5) != ".json") @@ -94,18 +91,18 @@ ) else virtual_map = load_map_config() - virtual_map.map_name = input("Choose the name for the map", "Map Name") as null|text + virtual_map.map_name = input(user, "Choose the name for the map", "Map Name") as null|text if(isnull(virtual_map.map_name)) virtual_map.map_name = "Custom" - var/shuttles = tgui_alert(usr,"Do you want to modify the shuttles?", "Map Shuttles", list("Yes", "No")) + var/shuttles = tgui_alert(user,"Do you want to modify the shuttles?", "Map Shuttles", list("Yes", "No")) if(shuttles == "Yes") for(var/s in virtual_map.shuttles) - var/shuttle = input(s, "Map Shuttles") as null|text + var/shuttle = input(user, s, "Map Shuttles") as null|text if(!shuttle) continue if(!SSmapping.shuttle_templates[shuttle]) - to_chat(usr, span_warning("No such shuttle as '[shuttle]' exists, using default.")) + to_chat(user, span_warning("No such shuttle as '[shuttle]' exists, using default.")) continue virtual_map.shuttles[s] = shuttle @@ -123,13 +120,13 @@ text2file(json_encode(json_value), PATH_TO_NEXT_MAP_JSON) if(SSmapping.changemap(virtual_map)) - message_admins("[key_name_admin(usr)] has changed the map to [virtual_map.map_name]") + message_admins("[key_name_admin(user)] has changed the map to [virtual_map.map_name]") SSmapping.map_force_chosen = TRUE fdel("data/custom_map_json/[config_file]") else var/datum/map_config/virtual_map = maprotatechoices[chosenmap] - message_admins("[key_name_admin(usr)] is changing the map to [virtual_map.map_name]") - log_admin("[key_name(usr)] is changing the map to [virtual_map.map_name]") + message_admins("[key_name_admin(user)] is changing the map to [virtual_map.map_name]") + log_admin("[key_name(user)] is changing the map to [virtual_map.map_name]") if (SSmapping.changemap(virtual_map)) - message_admins("[key_name_admin(usr)] has changed the map to [virtual_map.map_name]") + message_admins("[key_name_admin(user)] has changed the map to [virtual_map.map_name]") SSmapping.map_force_chosen = TRUE diff --git a/code/modules/admin/verbs/panicbunker.dm b/code/modules/admin/verbs/panicbunker.dm index c8c47858669..57aba1ee8d9 100644 --- a/code/modules/admin/verbs/panicbunker.dm +++ b/code/modules/admin/verbs/panicbunker.dm @@ -1,8 +1,6 @@ -/client/proc/panicbunker() - set category = "Server" - set name = "Toggle Panic Bunker" +ADMIN_VERB(panic_bunker, R_SERVER, "Toggle Panic Bunker", "Toggles the panic bunker for the server.", ADMIN_CATEGORY_SERVER) if (!CONFIG_GET(flag/sql_enabled)) - to_chat(usr, span_adminnotice("The Database is not enabled!"), confidential = TRUE) + to_chat(user, span_adminnotice("The Database is not enabled!"), confidential = TRUE) return var/new_pb = !CONFIG_GET(flag/panic_bunker) @@ -10,28 +8,26 @@ var/time_rec = 0 var/message = "" if(new_pb) - time_rec = input(src, "How many living minutes should they need to play? 0 to disable.", "Shit's fucked isn't it", CONFIG_GET(number/panic_bunker_living)) as num - message = input(src, "What should they see when they log in?", "MMM", CONFIG_GET(string/panic_bunker_message)) as text + time_rec = input(user, "How many living minutes should they need to play? 0 to disable.", "Shit's fucked isn't it", CONFIG_GET(number/panic_bunker_living)) as num + message = input(user, "What should they see when they log in?", "MMM", CONFIG_GET(string/panic_bunker_message)) as text message = replacetext(message, "%minutes%", time_rec) CONFIG_SET(number/panic_bunker_living, time_rec) CONFIG_SET(string/panic_bunker_message, message) - var/interview_sys = tgui_alert(usr, "Should the interview system be enabled? (Allows players to connect under the hour limit and force them to be manually approved to play)", "Enable interviews?", list("Enable", "Disable")) + var/interview_sys = tgui_alert(user, "Should the interview system be enabled? (Allows players to connect under the hour limit and force them to be manually approved to play)", "Enable interviews?", list("Enable", "Disable")) interview = interview_sys == "Enable" CONFIG_SET(flag/panic_bunker_interview, interview) CONFIG_SET(flag/panic_bunker, new_pb) - log_admin("[key_name(usr)] has toggled the Panic Bunker, it is now [new_pb ? "on and set to [time_rec] with a message of [message]. The interview system is [interview ? "enabled" : "disabled"]" : "off"].") - message_admins("[key_name_admin(usr)] has toggled the Panic Bunker, it is now [new_pb ? "enabled with a living minutes requirement of [time_rec]. The interview system is [interview ? "enabled" : "disabled"]" : "disabled"].") + log_admin("[key_name(user)] has toggled the Panic Bunker, it is now [new_pb ? "on and set to [time_rec] with a message of [message]. The interview system is [interview ? "enabled" : "disabled"]" : "off"].") + message_admins("[key_name_admin(user)] has toggled the Panic Bunker, it is now [new_pb ? "enabled with a living minutes requirement of [time_rec]. The interview system is [interview ? "enabled" : "disabled"]" : "disabled"].") if (new_pb && !SSdbcore.Connect()) message_admins("The Database is not connected! Panic bunker will not work until the connection is reestablished.") SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Panic Bunker", "[new_pb ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! -/client/proc/toggle_interviews() - set category = "Server" - set name = "Toggle PB Interviews" +ADMIN_VERB(toggle_interviews, R_SERVER, "Toggle PB Interviews", "Toggle whether new players will be interviewed or blocked from connecting.", ADMIN_CATEGORY_SERVER) if (!CONFIG_GET(flag/panic_bunker)) - to_chat(usr, span_adminnotice("NOTE: The panic bunker is not enabled, so this change will not effect anything until it is enabled."), confidential = TRUE) + to_chat(user, span_adminnotice("NOTE: The panic bunker is not enabled, so this change will not effect anything until it is enabled."), confidential = TRUE) var/new_interview = !CONFIG_GET(flag/panic_bunker_interview) CONFIG_SET(flag/panic_bunker_interview, new_interview) - log_admin("[key_name(usr)] has toggled the Panic Bunker's interview system, it is now [new_interview ? "enabled" : "disabled"].") - message_admins("[key_name(usr)] has toggled the Panic Bunker's interview system, it is now [new_interview ? "enabled" : "disabled"].") + log_admin("[key_name(user)] has toggled the Panic Bunker's interview system, it is now [new_interview ? "enabled" : "disabled"].") + message_admins("[key_name(user)] has toggled the Panic Bunker's interview system, it is now [new_interview ? "enabled" : "disabled"].") diff --git a/code/modules/admin/verbs/player_ticket_history.dm b/code/modules/admin/verbs/player_ticket_history.dm index ac87707e98d..829d4dfc2b5 100644 --- a/code/modules/admin/verbs/player_ticket_history.dm +++ b/code/modules/admin/verbs/player_ticket_history.dm @@ -19,13 +19,8 @@ GENERAL_PROTECT_DATUM(/datum/ticket_log_entry) GLOBAL_DATUM_INIT(player_ticket_history, /datum/ticket_history_holder, new) GLOBAL_PROTECT(player_ticket_history) -/client/proc/player_ticket_history() - set name = "Player Ticket History" - set desc = "Allows you to view the ticket history of a player." - set category = "Admin" - if(!check_rights(R_ADMIN)) - return - GLOB.player_ticket_history.ui_interact(mob) +ADMIN_VERB(player_ticket_history, R_ADMIN, "Player Ticket History", "Allows you to view the ticket history of a player.", ADMIN_CATEGORY_MAIN) + GLOB.player_ticket_history.ui_interact(user.mob) /datum/ticket_history_holder /// Assosciative list of ticket histories. ckey -> list/datum/ticket_history @@ -34,7 +29,7 @@ GLOBAL_PROTECT(player_ticket_history) var/list/user_selections = list() /datum/ticket_history_holder/proc/cache_history_for_ckey(ckey, entries = 5) - ckey = lowertext(ckey) + ckey = LOWER_TEXT(ckey) if(!isnum(entries) || entries <= 0) return diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm index 1b63c83529b..c4e4257e84f 100644 --- a/code/modules/admin/verbs/playsound.dm +++ b/code/modules/admin/verbs/playsound.dm @@ -3,20 +3,15 @@ #define SHELLEO_STDOUT 2 #define SHELLEO_STDERR 3 -/client/proc/play_sound(S as sound) - set category = "Admin.Fun" - set name = "Play Global Sound" - if(!check_rights(R_SOUND)) - return - +ADMIN_VERB(play_sound, R_SOUND, "Play Global Sound", "Play a sound to all connected players.", ADMIN_CATEGORY_FUN, sound as sound) var/freq = 1 - var/vol = input(usr, "What volume would you like the sound to play at?",, 100) as null|num + var/vol = tgui_input_number(user, "What volume would you like the sound to play at?", max_value = 100) if(!vol) return vol = clamp(vol, 1, 100) - var/sound/admin_sound = new() - admin_sound.file = S + var/sound/admin_sound = new + admin_sound.file = sound admin_sound.priority = 250 admin_sound.channel = CHANNEL_ADMIN admin_sound.frequency = freq @@ -25,15 +20,15 @@ admin_sound.status = SOUND_STREAM admin_sound.volume = vol - var/res = tgui_alert(usr, "Show the title of this song to the players?",, list("Yes","No", "Cancel")) + var/res = tgui_alert(user, "Show the title of this song to the players?",, list("Yes","No", "Cancel")) switch(res) if("Yes") - to_chat(world, span_boldannounce("An admin played: [S]"), confidential = TRUE) + to_chat(world, span_boldannounce("An admin played: [sound]"), confidential = TRUE) if("Cancel") return - log_admin("[key_name(src)] played sound [S]") - message_admins("[key_name_admin(src)] played sound [S]") + log_admin("[key_name(user)] played sound [sound]") + message_admins("[key_name_admin(user)] played sound [sound]") for(var/mob/M in GLOB.player_list) if(M.client.prefs.read_preference(/datum/preference/toggle/sound_midi)) @@ -43,31 +38,20 @@ BLACKBOX_LOG_ADMIN_VERB("Play Global Sound") - -/client/proc/play_local_sound(S as sound) - set category = "Admin.Fun" - set name = "Play Local Sound" - if(!check_rights(R_SOUND)) - return - - log_admin("[key_name(src)] played a local sound [S]") - message_admins("[key_name_admin(src)] played a local sound [S]") - playsound(get_turf(src.mob), S, 50, FALSE, FALSE) +ADMIN_VERB(play_local_sound, R_SOUND, "Play Local Sound", "Plays a sound only you can hear.", ADMIN_CATEGORY_FUN, sound as sound) + log_admin("[key_name(user)] played a local sound [sound]") + message_admins("[key_name_admin(user)] played a local sound [sound]") + playsound(get_turf(user.mob), sound, 50, FALSE, FALSE) BLACKBOX_LOG_ADMIN_VERB("Play Local Sound") -/client/proc/play_direct_mob_sound(S as sound, mob/M) - set category = "Admin.Fun" - set name = "Play Direct Mob Sound" - if(!check_rights(R_SOUND)) +ADMIN_VERB(play_direct_mob_sound, R_SOUND, "Play Direct Mob Sound", "Play a sound directly to a mob.", ADMIN_CATEGORY_FUN, sound as sound, mob/target in world) + if(!target) + target = input(user, "Choose a mob to play the sound to. Only they will hear it.", "Play Mob Sound") as null|anything in sort_names(GLOB.player_list) + if(QDELETED(target)) return - - if(!M) - M = input(usr, "Choose a mob to play the sound to. Only they will hear it.", "Play Mob Sound") as null|anything in sort_names(GLOB.player_list) - if(!M || QDELETED(M)) - return - log_admin("[key_name(src)] played a direct mob sound [S] to [M].") - message_admins("[key_name_admin(src)] played a direct mob sound [S] to [ADMIN_LOOKUPFLW(M)].") - SEND_SOUND(M, S) + log_admin("[key_name(user)] played a direct mob sound [sound] to [key_name_admin(target)].") + message_admins("[key_name_admin(user)] played a direct mob sound [sound] to [ADMIN_LOOKUPFLW(target)].") + SEND_SOUND(target, sound) BLACKBOX_LOG_ADMIN_VERB("Play Direct Mob Sound") ///Takes an input from either proc/play_web_sound or the request manager and runs it through youtube-dl and prompts the user before playing it to the server. @@ -169,59 +153,41 @@ BLACKBOX_LOG_ADMIN_VERB("Play Internet Sound") +ADMIN_VERB_CUSTOM_EXIST_CHECK(play_web_sound) + return !!CONFIG_GET(string/invoke_youtubedl) -/client/proc/play_web_sound() - set category = "Admin.Fun" - set name = "Play Internet Sound" - if(!check_rights(R_SOUND)) - return - - var/ytdl = CONFIG_GET(string/invoke_youtubedl) - if(!ytdl) - to_chat(src, span_boldwarning("Youtube-dl was not configured, action unavailable"), confidential = TRUE) //Check config.txt for the INVOKE_YOUTUBEDL value - return - +ADMIN_VERB(play_web_sound, R_SOUND, "Play Internet Sound", "Play a given internet sound to all players.", ADMIN_CATEGORY_FUN) if(S_TIMER_COOLDOWN_TIMELEFT(SStimer, COOLDOWN_INTERNET_SOUND)) - if(tgui_alert(usr, "Someone else is already playing an Internet sound! It has [DisplayTimeText(S_TIMER_COOLDOWN_TIMELEFT(SStimer, COOLDOWN_INTERNET_SOUND), 1)] remaining. \ + if(tgui_alert(user, "Someone else is already playing an Internet sound! It has [DisplayTimeText(S_TIMER_COOLDOWN_TIMELEFT(SStimer, COOLDOWN_INTERNET_SOUND), 1)] remaining. \ Would you like to override?", "Musicalis Interruptus", list("No","Yes")) != "Yes") return - var/web_sound_input = tgui_input_text(usr, "Enter content URL (supported sites only, leave blank to stop playing)", "Play Internet Sound", null) + var/web_sound_input = tgui_input_text(user, "Enter content URL (supported sites only, leave blank to stop playing)", "Play Internet Sound", null) if(length(web_sound_input)) web_sound_input = trim(web_sound_input) if(findtext(web_sound_input, ":") && !findtext(web_sound_input, GLOB.is_http_protocol)) - to_chat(src, span_boldwarning("Non-http(s) URIs are not allowed."), confidential = TRUE) - to_chat(src, span_warning("For youtube-dl shortcuts like ytsearch: please use the appropriate full URL from the website."), confidential = TRUE) + to_chat(user, span_boldwarning("Non-http(s) URIs are not allowed."), confidential = TRUE) + to_chat(user, span_warning("For youtube-dl shortcuts like ytsearch: please use the appropriate full URL from the website."), confidential = TRUE) return - web_sound(usr, web_sound_input) + web_sound(user.mob, web_sound_input) else - web_sound(usr, null) + web_sound(user.mob, null) -/client/proc/set_round_end_sound(S as sound) - set category = "Admin.Fun" - set name = "Set Round End Sound" - if(!check_rights(R_SOUND)) - return +ADMIN_VERB(set_round_end_sound, R_SOUND, "Set Round End Sound", "Set the sound that plays on round end.", ADMIN_CATEGORY_FUN, sound as sound) + SSticker.SetRoundEndSound(sound) - SSticker.SetRoundEndSound(S) - - log_admin("[key_name(src)] set the round end sound to [S]") - message_admins("[key_name_admin(src)] set the round end sound to [S]") + log_admin("[key_name(user)] set the round end sound to [sound]") + message_admins("[key_name_admin(user)] set the round end sound to [sound]") BLACKBOX_LOG_ADMIN_VERB("Set Round End Sound") -/client/proc/stop_sounds() - set category = "Debug" - set name = "Stop All Playing Sounds" - if(!src.holder) - return - - log_admin("[key_name(src)] stopped all currently playing sounds.") - message_admins("[key_name_admin(src)] stopped all currently playing sounds.") - for(var/mob/M in GLOB.player_list) - SEND_SOUND(M, sound(null)) - var/client/C = M.client - C?.tgui_panel?.stop_music() +ADMIN_VERB(stop_sounds, R_NONE, "Stop All Playing Sounds", "Stops all playing sounds for EVERYONE.", ADMIN_CATEGORY_DEBUG) + log_admin("[key_name(user)] stopped all currently playing sounds.") + message_admins("[key_name_admin(user)] stopped all currently playing sounds.") + for(var/mob/player as anything in GLOB.player_list) + SEND_SOUND(player, sound(null)) + var/client/player_client = player.client + player_client?.tgui_panel?.stop_music() S_TIMER_COOLDOWN_RESET(SStimer, COOLDOWN_INTERNET_SOUND) BLACKBOX_LOG_ADMIN_VERB("Stop All Playing Sounds") diff --git a/code/modules/admin/verbs/possess.dm b/code/modules/admin/verbs/possess.dm index 63304104ab5..a7e50840f5e 100644 --- a/code/modules/admin/verbs/possess.dm +++ b/code/modules/admin/verbs/possess.dm @@ -1,32 +1,20 @@ -/proc/possess(obj/target in world) - set name = "Possess Obj" - set category = "Object" - var/result = usr.AddComponent(/datum/component/object_possession, target) +ADMIN_VERB(possess, R_POSSESS, "Possess Obj", "Possess an object.", ADMIN_CATEGORY_OBJECT, obj/target in world) + var/result = user.mob.AddComponent(/datum/component/object_possession, target) if(isnull(result)) // trigger a safety movement just in case we yonk - usr.forceMove(get_turf(usr)) + user.mob.forceMove(get_turf(user.mob)) return var/turf/target_turf = get_turf(target) - var/message = "[key_name(usr)] has possessed [target] ([target.type]) at [AREACOORD(target_turf)]" + var/message = "[key_name(user)] has possessed [target] ([target.type]) at [AREACOORD(target_turf)]" message_admins(message) log_admin(message) BLACKBOX_LOG_ADMIN_VERB("Possess Object") -/proc/release() - set name = "Release Obj" - set category = "Object" - - qdel(usr.GetComponent(/datum/component/object_possession)) +ADMIN_VERB(release, R_POSSESS, "Release Object", "Stop possessing an object.", ADMIN_CATEGORY_OBJECT) + var/possess_component = user.mob.GetComponent(/datum/component/object_possession) + if(!isnull(possess_component)) + qdel(possess_component) BLACKBOX_LOG_ADMIN_VERB("Release Object") - -/proc/give_possession_verbs(mob/dude in GLOB.mob_list) - set desc = "Give this guy possess/release verbs" - set category = "Debug" - set name = "Give Possessing Verbs" - - add_verb(dude, GLOBAL_PROC_REF(possess)) - add_verb(dude, GLOBAL_PROC_REF(release)) - BLACKBOX_LOG_ADMIN_VERB("Give Possessing Verbs") diff --git a/code/modules/admin/verbs/reestablish_db_connection.dm b/code/modules/admin/verbs/reestablish_db_connection.dm index a299eb43b0f..5c3701c97b0 100644 --- a/code/modules/admin/verbs/reestablish_db_connection.dm +++ b/code/modules/admin/verbs/reestablish_db_connection.dm @@ -1,26 +1,24 @@ -/client/proc/reestablish_db_connection() - set category = "Server" - set name = "Reestablish DB Connection" +ADMIN_VERB(reestablish_db_connection, R_NONE, "Reestablish DB Connection", "Attempts to (re)establish the DB Connection", ADMIN_CATEGORY_SERVER) if (!CONFIG_GET(flag/sql_enabled)) - to_chat(usr, span_adminnotice("The Database is not enabled!"), confidential = TRUE) + to_chat(user, span_adminnotice("The Database is not enabled!"), confidential = TRUE) return if (SSdbcore.IsConnected()) - if (!check_rights(R_DEBUG,0)) - tgui_alert(usr,"The database is already connected! (Only those with +debug can force a reconnection)", "The database is already connected!") + if (!user.holder.check_for_rights(R_DEBUG)) + tgui_alert(user,"The database is already connected! (Only those with +debug can force a reconnection)", "The database is already connected!") return - var/reconnect = tgui_alert(usr,"The database is already connected! If you *KNOW* that this is incorrect, you can force a reconnection", "The database is already connected!", list("Force Reconnect", "Cancel")) + var/reconnect = tgui_alert(user,"The database is already connected! If you *KNOW* that this is incorrect, you can force a reconnection", "The database is already connected!", list("Force Reconnect", "Cancel")) if (reconnect != "Force Reconnect") return SSdbcore.Disconnect() - log_admin("[key_name(usr)] has forced the database to disconnect") - message_admins("[key_name_admin(usr)] has forced the database to disconnect!") + log_admin("[key_name(user)] has forced the database to disconnect") + message_admins("[key_name_admin(user)] has forced the database to disconnect!") BLACKBOX_LOG_ADMIN_VERB("Force Reestablished Database Connection") - log_admin("[key_name(usr)] is attempting to re-establish the DB Connection") - message_admins("[key_name_admin(usr)] is attempting to re-establish the DB Connection") + log_admin("[key_name(user)] is attempting to re-establish the DB Connection") + message_admins("[key_name_admin(user)] is attempting to re-establish the DB Connection") BLACKBOX_LOG_ADMIN_VERB("Reestablished Database Connection") SSdbcore.failed_connections = 0 diff --git a/code/modules/admin/verbs/requests.dm b/code/modules/admin/verbs/requests.dm index 2cd32648b67..53d3e092f81 100644 --- a/code/modules/admin/verbs/requests.dm +++ b/code/modules/admin/verbs/requests.dm @@ -1,7 +1,4 @@ -/// Verb for opening the requests manager panel -/client/proc/requests() - set name = "Requests Manager" - set desc = "Open the request manager panel to view all requests during this round" - set category = "Admin.Game" - BLACKBOX_LOG_ADMIN_VERB("Request Manager") + +ADMIN_VERB(requests, R_NONE, "Requests Manager", "Open the request manager panel to view all requests during this round", ADMIN_CATEGORY_GAME) GLOB.requests.ui_interact(usr) + BLACKBOX_LOG_ADMIN_VERB("Request Manager") diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm index e70138ad8ac..b7aa16b6b5f 100644 --- a/code/modules/admin/verbs/secrets.dm +++ b/code/modules/admin/verbs/secrets.dm @@ -1,12 +1,9 @@ GLOBAL_DATUM(everyone_an_antag, /datum/everyone_is_an_antag_controller) -/client/proc/secrets() //Creates a verb for admins to open up the ui - set name = "Secrets" - set desc = "Abuse harder than you ever have before with this handy dandy semi-misc stuff menu" - set category = "Admin.Game" +ADMIN_VERB(secrets, R_NONE, "Secrets", "Abuse harder than you ever have before with this handy dandy semi-misc stuff menu.", ADMIN_CATEGORY_GAME) + var/datum/secrets_menu/tgui = new(user) + tgui.ui_interact(user.mob) BLACKBOX_LOG_ADMIN_VERB("Secrets Panel") - var/datum/secrets_menu/tgui = new(usr)//create the datum - tgui.ui_interact(usr)//datum has a tgui component, here we open the window /datum/secrets_menu var/client/holder //client of whoever is using this datum @@ -102,25 +99,25 @@ GLOBAL_DATUM(everyone_an_antag, /datum/everyone_is_an_antag_controller) D.cure(0) if("list_bombers") - holder.list_bombers() + holder.holder.list_bombers() if("list_signalers") - holder.list_signalers() + holder.holder.list_signalers() if("list_lawchanges") - holder.list_law_changes() + holder.holder.list_law_changes() if("showailaws") - holder.check_ai_laws() + holder.holder.list_law_changes() if("manifest") - holder.show_manifest() + holder.holder.show_manifest() if("dna") - holder.list_dna() + holder.holder.list_dna() if("fingerprints") - holder.list_fingerprints() + holder.holder.list_fingerprints() if("ctfbutton") toggle_id_ctf(holder, CTF_GHOST_CTF_GAME_ID) diff --git a/code/modules/admin/verbs/selectequipment.dm b/code/modules/admin/verbs/selectequipment.dm index 59513db0129..b94fd5cb2e4 100644 --- a/code/modules/admin/verbs/selectequipment.dm +++ b/code/modules/admin/verbs/selectequipment.dm @@ -1,10 +1,6 @@ -/client/proc/cmd_select_equipment(mob/target in GLOB.mob_list) - set category = "Admin.Events" - set name = "Select equipment" - - - var/datum/select_equipment/ui = new(usr, target) - ui.ui_interact(usr) +ADMIN_VERB_ONLY_CONTEXT_MENU(select_equipment, R_FUN, "Select Equipment", mob/target in world) + var/datum/select_equipment/ui = new(user, target) + ui.ui_interact(user.mob) /* * This is the datum housing the select equipment UI. @@ -152,7 +148,7 @@ return custom_outfit -/datum/select_equipment/ui_act(action, params) +/datum/select_equipment/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) if(..()) return . = TRUE @@ -181,7 +177,7 @@ user.admin_apply_outfit(target_mob, new_outfit) if("customoutfit") - user.outfit_manager() + return SSadmin_verbs.dynamic_invoke_verb(ui.user, /datum/admin_verb/outfit_manager) if("togglefavorite") var/datum/outfit/outfit_path = resolve_outfit(params["path"]) diff --git a/code/modules/admin/verbs/server.dm b/code/modules/admin/verbs/server.dm index d93008996bc..71000fd310d 100644 --- a/code/modules/admin/verbs/server.dm +++ b/code/modules/admin/verbs/server.dm @@ -1,191 +1,148 @@ // Server Tab - Server Verbs -/client/proc/toggle_random_events() - set category = "Server" - set name = "Toggle random events on/off" - set desc = "Toggles random events such as meteors, black holes, blob (but not space dust) on/off" +ADMIN_VERB(toggle_random_events, R_SERVER, "Toggle Random Events", "Toggles random events on or off.", ADMIN_CATEGORY_SERVER) var/new_are = !CONFIG_GET(flag/allow_random_events) CONFIG_SET(flag/allow_random_events, new_are) - message_admins("[key_name_admin(usr)] has [new_are ? "enabled" : "disabled"] random events.") + message_admins("[key_name_admin(user)] has [new_are ? "enabled" : "disabled"] random events.") SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Random Events", "[new_are ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! -/client/proc/toggle_hub() - set category = "Server" - set name = "Toggle Hub" - +ADMIN_VERB(toggle_hub, R_SERVER, "Toggle Hub", "Toggles the server's visilibility on the BYOND Hub.", ADMIN_CATEGORY_SERVER) world.update_hub_visibility(!GLOB.hub_visibility) - log_admin("[key_name(usr)] has toggled the server's hub status for the round, it is now [(GLOB.hub_visibility?"on":"off")] the hub.") - message_admins("[key_name_admin(usr)] has toggled the server's hub status for the round, it is now [(GLOB.hub_visibility?"on":"off")] the hub.") + log_admin("[key_name(user)] has toggled the server's hub status for the round, it is now [(GLOB.hub_visibility?"on":"off")] the hub.") + message_admins("[key_name_admin(user)] has toggled the server's hub status for the round, it is now [(GLOB.hub_visibility?"on":"off")] the hub.") if (GLOB.hub_visibility && !world.reachable) message_admins("WARNING: The server will not show up on the hub because byond is detecting that a filewall is blocking incoming connections.") SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggled Hub Visibility", "[GLOB.hub_visibility ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! -/datum/admins/proc/restart() - set category = "Server" - set name = "Reboot World" - set desc = "Restarts the world immediately" - if (!usr.client.holder) - return - - var/localhost_addresses = list("127.0.0.1", "::1") +ADMIN_VERB(restart, R_SERVER, "Reboot World", "Restarts the world immediately.", ADMIN_CATEGORY_SERVER) var/list/options = list("Regular Restart", "Regular Restart (with delay)", "Hard Restart (No Delay/Feeback Reason)", "Hardest Restart (No actions, just reboot)") if(world.TgsAvailable()) options += "Server Restart (Kill and restart DD)"; if(SSticker.admin_delay_notice) - if(alert(usr, "Are you sure? An admin has already delayed the round end for the following reason: [SSticker.admin_delay_notice]", "Confirmation", "Yes", "No") != "Yes") + if(alert(user, "Are you sure? An admin has already delayed the round end for the following reason: [SSticker.admin_delay_notice]", "Confirmation", "Yes", "No") != "Yes") return FALSE - var/result = input(usr, "Select reboot method", "World Reboot", options[1]) as null|anything in options - if(result) - BLACKBOX_LOG_ADMIN_VERB("Reboot World") - var/init_by = "Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key]." - switch(result) - if("Regular Restart") - if(!(isnull(usr.client.address) || (usr.client.address in localhost_addresses))) - if(alert(usr, "Are you sure you want to restart the server?","This server is live", "Restart", "Cancel") != "Restart") - return FALSE - SSticker.Reboot(init_by, "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", 10) - if("Regular Restart (with delay)") - var/delay = input("What delay should the restart have (in seconds)?", "Restart Delay", 5) as num|null - if(!delay) + var/result = input(user, "Select reboot method", "World Reboot", options[1]) as null|anything in options + if(isnull(result)) + return + + BLACKBOX_LOG_ADMIN_VERB("Reboot World") + var/init_by = "Initiated by [user.holder.fakekey ? "Admin" : user.key]." + switch(result) + if("Regular Restart") + if(!user.is_localhost()) + if(alert(user, "Are you sure you want to restart the server?","This server is live", "Restart", "Cancel") != "Restart") return FALSE - if(!(isnull(usr.client.address) || (usr.client.address in localhost_addresses))) - if(alert(usr,"Are you sure you want to restart the server?","This server is live", "Restart", "Cancel") != "Restart") - return FALSE - SSticker.Reboot(init_by, "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", delay * 10) - if("Hard Restart (No Delay, No Feeback Reason)") - to_chat(world, "World reboot - [init_by]") - world.Reboot() - if("Hardest Restart (No actions, just reboot)") - to_chat(world, "Hard world reboot - [init_by]") - world.Reboot(fast_track = TRUE) - if("Server Restart (Kill and restart DD)") - to_chat(world, "Server restart - [init_by]") - world.TgsEndProcess() + SSticker.Reboot(init_by, "admin reboot - by [user.key] [user.holder.fakekey ? "(stealth)" : ""]", 10) + if("Regular Restart (with delay)") + var/delay = input("What delay should the restart have (in seconds)?", "Restart Delay", 5) as num|null + if(!delay) + return FALSE + if(!user.is_localhost()) + if(alert(user,"Are you sure you want to restart the server?","This server is live", "Restart", "Cancel") != "Restart") + return FALSE + SSticker.Reboot(init_by, "admin reboot - by [user.key] [user.holder.fakekey ? "(stealth)" : ""]", delay * 10) + if("Hard Restart (No Delay, No Feeback Reason)") + to_chat(world, "World reboot - [init_by]") + world.Reboot() + if("Hardest Restart (No actions, just reboot)") + to_chat(world, "Hard world reboot - [init_by]") + world.Reboot(fast_track = TRUE) + if("Server Restart (Kill and restart DD)") + to_chat(world, "Server restart - [init_by]") + world.TgsEndProcess() -/datum/admins/proc/end_round() - set category = "Server" - set name = "End Round" - set desc = "Attempts to produce a round end report and then restart the server organically." - - if (!usr.client.holder) +ADMIN_VERB(end_round, R_SERVER, "End Round", "Forcibly ends the round and allows the server to restart normally.", ADMIN_CATEGORY_SERVER) + var/confirm = tgui_alert(user, "End the round and restart the game world?", "End Round", list("Yes", "Cancel")) + if(confirm != "Yes") return - var/confirm = tgui_alert(usr, "End the round and restart the game world?", "End Round", list("Yes", "Cancel")) - if(confirm == "Cancel") - return - if(confirm == "Yes") - SSticker.force_ending = FORCE_END_ROUND - BLACKBOX_LOG_ADMIN_VERB("End Round") + SSticker.force_ending = FORCE_END_ROUND + BLACKBOX_LOG_ADMIN_VERB("End Round") -/datum/admins/proc/toggleooc() - set category = "Server" - set desc = "Toggle dis bitch" - set name = "Toggle OOC" +ADMIN_VERB(toggle_ooc, R_ADMIN, "Toggle OOC", "Toggle the OOC channel on or off.", ADMIN_CATEGORY_SERVER) toggle_ooc() - log_admin("[key_name(usr)] toggled OOC.") - message_admins("[key_name_admin(usr)] toggled OOC.") - SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle OOC", "[GLOB.ooc_allowed ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! + log_admin("[key_name(user)] toggled OOC.") + message_admins("[key_name_admin(user)] toggled OOC.") + SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle OOC", "[GLOB.ooc_allowed ? "Enabled" : "Disabled"]")) -/datum/admins/proc/toggleoocdead() - set category = "Server" - set desc = "Toggle dis bitch" - set name = "Toggle Dead OOC" +ADMIN_VERB(toggle_ooc_dead, R_ADMIN, "Toggle Dead OOC", "Toggle the OOC channel for dead players on or off.", ADMIN_CATEGORY_SERVER) toggle_dooc() + log_admin("[key_name(user)] toggled OOC.") + message_admins("[key_name_admin(user)] toggled Dead OOC.") + SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Dead OOC", "[GLOB.dooc_allowed ? "Enabled" : "Disabled"]")) - log_admin("[key_name(usr)] toggled OOC.") - message_admins("[key_name_admin(usr)] toggled Dead OOC.") - SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Dead OOC", "[GLOB.dooc_allowed ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! +ADMIN_VERB(start_now, R_SERVER, "Start Now", "Start the round RIGHT NOW.", ADMIN_CATEGORY_SERVER) + var/static/list/waiting_states = list(GAME_STATE_PREGAME, GAME_STATE_STARTUP) + if(!(SSticker.current_state in waiting_states)) + to_chat(user, span_warning(span_red("The game has already started!"))) + return -/datum/admins/proc/startnow() - set category = "Server" - set desc = "Start the round RIGHT NOW" - set name = "Start Now" - if(SSticker.current_state == GAME_STATE_PREGAME || SSticker.current_state == GAME_STATE_STARTUP) - if(!SSticker.start_immediately) - var/localhost_addresses = list("127.0.0.1", "::1") - if(!(isnull(usr.client.address) || (usr.client.address in localhost_addresses))) - if(tgui_alert(usr, "Are you sure you want to start the round?","Start Now",list("Start Now","Cancel")) != "Start Now") - return FALSE - SSticker.start_immediately = TRUE - log_admin("[usr.key] has started the game.") - var/msg = "" - if(SSticker.current_state == GAME_STATE_STARTUP) - msg = " (The server is still setting up, but the round will be \ - started as soon as possible.)" - message_admins("[usr.key] has started the game.[msg]") - BLACKBOX_LOG_ADMIN_VERB("Start Now") - return TRUE + if(SSticker.start_immediately) SSticker.start_immediately = FALSE SSticker.SetTimeLeft(1800) - to_chat(world, "The game will start in 180 seconds.") + to_chat(world, span_infoplain(span_bold("The game will start in 180 seconds."))) SEND_SOUND(world, sound('sound/ai/default/attention.ogg')) - message_admins("[usr.key] has cancelled immediate game start. Game will start in 180 seconds.") - log_admin("[usr.key] has cancelled immediate game start.") - else - to_chat(usr, "Error: Start Now: Game has already started.") - return FALSE - -/datum/admins/proc/delay_round_end() - set category = "Server" - set desc = "Prevent the server from restarting" - set name = "Delay Round End" - - if(!check_rights(R_ADMIN)) // SKYRAT EDIT - Admins can delay the round end - ORIGINAL: if(!check_rights(R_SERVER)) + message_admins(span_adminnotice("[key_name_admin(user)] has cancelled immediate game start. Game will start in 3 minutes.")) + log_admin("[key_name(user)] has cancelled immediate game start.") return + if(!user.is_localhost()) + var/response = tgui_alert(user, "Are you sure you want to start the round?", "Start Now", list("Start Now", "Cancel")) + if(response != "Start Now") + return + SSticker.start_immediately = TRUE + + log_admin("[key_name(user)] has started the game.") + message_admins("[key_name_admin(user)] has started the game.") + if(SSticker.current_state == GAME_STATE_STARTUP) + message_admins("The server is still setting up, but the round will be started as soon as possible.") + BLACKBOX_LOG_ADMIN_VERB("Start Now") + +// ADMIN_VERB(delay_round_end, R_SERVER, "Delay Round End", "Prevent the server from restarting.", ADMIN_CATEGORY_SERVER) +ADMIN_VERB(delay_round_end, R_ADMIN, "Delay Round End", "Prevent the server from restarting.", ADMIN_CATEGORY_SERVER) // SKYRAT EDIT -- ORIGINAL ABOVE if(SSticker.delay_end) - tgui_alert(usr, "The round end is already delayed. The reason for the current delay is: \"[SSticker.admin_delay_notice]\"", "Alert", list("Ok")) + tgui_alert(user, "The round end is already delayed. The reason for the current delay is: \"[SSticker.admin_delay_notice]\"", "Alert", list("Ok")) return - var/delay_reason = input(usr, "Enter a reason for delaying the round end", "Round Delay Reason") as null|text + var/delay_reason = input(user, "Enter a reason for delaying the round end", "Round Delay Reason") as null|text if(isnull(delay_reason)) return if(SSticker.delay_end) - tgui_alert(usr, "The round end is already delayed. The reason for the current delay is: \"[SSticker.admin_delay_notice]\"", "Alert", list("Ok")) + tgui_alert(user, "The round end is already delayed. The reason for the current delay is: \"[SSticker.admin_delay_notice]\"", "Alert", list("Ok")) return SSticker.delay_end = TRUE SSticker.admin_delay_notice = delay_reason - log_admin("[key_name(usr)] delayed the round end for reason: [SSticker.admin_delay_notice]") - message_admins("[key_name_admin(usr)] delayed the round end for reason: [SSticker.admin_delay_notice]") + log_admin("[key_name(user)] delayed the round end for reason: [SSticker.admin_delay_notice]") + message_admins("[key_name_admin(user)] delayed the round end for reason: [SSticker.admin_delay_notice]") SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Delay Round End", "Reason: [delay_reason]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! -/datum/admins/proc/toggleenter() - set category = "Server" - set desc = "People can't enter" - set name = "Toggle Entering" +ADMIN_VERB(toggle_enter, R_SERVER, "Toggle Entering", "Toggle the ability to enter the game.", ADMIN_CATEGORY_SERVER) if(!SSlag_switch.initialized) return SSlag_switch.set_measure(DISABLE_NON_OBSJOBS, !SSlag_switch.measures[DISABLE_NON_OBSJOBS]) - log_admin("[key_name(usr)] toggled new player game entering. Lag Switch at index ([DISABLE_NON_OBSJOBS])") - message_admins("[key_name_admin(usr)] toggled new player game entering [SSlag_switch.measures[DISABLE_NON_OBSJOBS] ? "OFF" : "ON"].") + log_admin("[key_name(user)] toggled new player game entering. Lag Switch at index ([DISABLE_NON_OBSJOBS])") + message_admins("[key_name_admin(user)] toggled new player game entering [SSlag_switch.measures[DISABLE_NON_OBSJOBS] ? "OFF" : "ON"].") SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Entering", "[!SSlag_switch.measures[DISABLE_NON_OBSJOBS] ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! -/datum/admins/proc/toggleAI() - set category = "Server" - set desc = "People can't be AI" - set name = "Toggle AI" +ADMIN_VERB(toggle_ai, R_SERVER, "Toggle AI", "Toggle the ability to choose AI jobs.", ADMIN_CATEGORY_SERVER) var/alai = CONFIG_GET(flag/allow_ai) CONFIG_SET(flag/allow_ai, !alai) if (alai) - to_chat(world, "The AI job is no longer chooseable.", confidential = TRUE) + to_chat(world, span_bold("The AI job is no longer chooseable."), confidential = TRUE) else - to_chat(world, "The AI job is chooseable now.", confidential = TRUE) + to_chat(world, span_bold("The AI job is chooseable now."), confidential = TRUE) log_admin("[key_name(usr)] toggled AI allowed.") world.update_status() SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle AI", "[!alai ? "Disabled" : "Enabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! -/datum/admins/proc/toggleaban() - set category = "Server" - set desc = "Respawn basically" - set name = "Toggle Respawn" - +ADMIN_VERB(toggle_respawn, R_SERVER, "Toggle Respawn", "Toggle the ability to respawn.", ADMIN_CATEGORY_SERVER) var/respawn_state = CONFIG_GET(flag/allow_respawn) var/new_state = -1 var/new_state_text = "" @@ -203,80 +160,71 @@ if(RESPAWN_FLAG_NEW_CHARACTER) // respawn currently enabled for different slot characters only new_state = RESPAWN_FLAG_DISABLED new_state_text = "Disabled" - to_chat(world, span_bold("You may no longer respawn :("), confidential = TRUE) + to_chat(world, span_bold("You may no longer respawn."), confidential = TRUE) else WARNING("Invalid respawn state in config: [respawn_state]") if(new_state == -1) - to_chat(usr, span_warning("The config for respawn is set incorrectly, please complain to your nearest server host (or fix it yourself). \ + to_chat(user, span_warning("The config for respawn is set incorrectly, please complain to your nearest server host (or fix it yourself). \ In the meanwhile respawn has been set to \"Off\".")) new_state = RESPAWN_FLAG_DISABLED new_state_text = "Disabled" CONFIG_SET(flag/allow_respawn, new_state) - message_admins(span_adminnotice("[key_name_admin(usr)] toggled respawn to \"[new_state_text]\".")) - log_admin("[key_name(usr)] toggled respawn to \"[new_state_text]\".") + message_admins(span_adminnotice("[key_name_admin(user)] toggled respawn to \"[new_state_text]\".")) + log_admin("[key_name(user)] toggled respawn to \"[new_state_text]\".") world.update_status() SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Respawn", "[new_state_text]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! -/datum/admins/proc/delay() - set category = "Server" - set desc = "Delay the game start" - set name = "Delay Pre-Game" - - var/newtime = input("Set a new time in seconds. Set -1 for indefinite delay.","Set Delay",round(SSticker.GetTimeLeft()/10)) as num|null +ADMIN_VERB(delay, R_SERVER, "Delay Pre-Game", "Delay the game start.", ADMIN_CATEGORY_SERVER) + var/newtime = input(user, "Set a new time in seconds. Set -1 for indefinite delay.", "Set Delay", round(SSticker.GetTimeLeft()/10)) as num|null if(!newtime) return if(SSticker.current_state > GAME_STATE_PREGAME) - return tgui_alert(usr, "Too late... The game has already started!") + return tgui_alert(user, "Too late... The game has already started!") newtime = newtime*10 SSticker.SetTimeLeft(newtime) SSticker.start_immediately = FALSE if(newtime < 0) - to_chat(world, "The game start has been delayed.", confidential = TRUE) + to_chat(world, span_infoplain(span_bold("The game start has been delayed.")), confidential = TRUE) log_admin("[key_name(usr)] delayed the round start.") else - to_chat(world, "The game will start in [DisplayTimeText(newtime)].", confidential = TRUE) + to_chat(world, span_infoplain(span_bold("The game will start in [DisplayTimeText(newtime)].")), confidential = TRUE) SEND_SOUND(world, sound('sound/ai/default/attention.ogg')) - log_admin("[key_name(usr)] set the pre-game delay to [DisplayTimeText(newtime)].") + log_admin("[key_name(user)] set the pre-game delay to [DisplayTimeText(newtime)].") BLACKBOX_LOG_ADMIN_VERB("Delay Game Start") -/datum/admins/proc/set_admin_notice() - set category = "Server" - set name = "Set Admin Notice" - set desc ="Set an announcement that appears to everyone who joins the server. Only lasts this round" - if(!check_rights(0)) - return - - var/new_admin_notice = input(src,"Set a public notice for this round. Everyone who joins the server will see it.\n(Leaving it blank will delete the current notice):","Set Notice",GLOB.admin_notice) as message|null +ADMIN_VERB(set_admin_notice, R_SERVER, "Set Admin Notice", "Set an announcement that appears to everyone who joins the server. Only lasts this round.", ADMIN_CATEGORY_SERVER) + var/new_admin_notice = input( + user, + "Set a public notice for this round. Everyone who joins the server will see it.\n(Leaving it blank will delete the current notice):", + "Set Notice", + GLOB.admin_notice, + ) as message|null if(new_admin_notice == null) return if(new_admin_notice == GLOB.admin_notice) return if(new_admin_notice == "") - message_admins("[key_name(usr)] removed the admin notice.") - log_admin("[key_name(usr)] removed the admin notice:\n[GLOB.admin_notice]") + message_admins("[key_name(user)] removed the admin notice.") + log_admin("[key_name(user)] removed the admin notice:\n[GLOB.admin_notice]") else - message_admins("[key_name(usr)] set the admin notice.") - log_admin("[key_name(usr)] set the admin notice:\n[new_admin_notice]") + message_admins("[key_name(user)] set the admin notice.") + log_admin("[key_name(user)] set the admin notice:\n[new_admin_notice]") to_chat(world, span_adminnotice("Admin Notice:\n \t [new_admin_notice]"), confidential = TRUE) BLACKBOX_LOG_ADMIN_VERB("Set Admin Notice") GLOB.admin_notice = new_admin_notice - return -/datum/admins/proc/toggleguests() - set category = "Server" - set desc = "Guests can't enter" - set name = "Toggle guests" +ADMIN_VERB(toggle_guests, R_SERVER, "Toggle Guests", "Toggle the ability for guests to enter the game.", ADMIN_CATEGORY_SERVER) var/new_guest_ban = !CONFIG_GET(flag/guest_ban) CONFIG_SET(flag/guest_ban, new_guest_ban) if (new_guest_ban) - to_chat(world, "Guests may no longer enter the game.", confidential = TRUE) + to_chat(world, span_bold("Guests may no longer enter the game."), confidential = TRUE) else - to_chat(world, "Guests may now enter the game.", confidential = TRUE) + to_chat(world, span_bold("Guests may now enter the game."), confidential = TRUE) log_admin("[key_name(usr)] toggled guests game entering [!new_guest_ban ? "" : "dis"]allowed.") message_admins(span_adminnotice("[key_name_admin(usr)] toggled guests game entering [!new_guest_ban ? "" : "dis"]allowed.")) SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Guests", "[!new_guest_ban ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/shuttlepanel.dm b/code/modules/admin/verbs/shuttlepanel.dm index d7050c0467b..0a33acb0692 100644 --- a/code/modules/admin/verbs/shuttlepanel.dm +++ b/code/modules/admin/verbs/shuttlepanel.dm @@ -1,13 +1,5 @@ -/datum/admins/proc/open_shuttlepanel() - set category = "Admin.Events" - set name = "Shuttle Manipulator" - set desc = "Opens the shuttle manipulator UI." - - if(!check_rights(R_ADMIN)) - return - - SSshuttle.ui_interact(usr) - +ADMIN_VERB(shuttle_panel, R_ADMIN, "Shuttle Manipulator", "Opens the shuttle manipulator UI.", ADMIN_CATEGORY_EVENTS) + SSshuttle.ui_interact(user.mob) /obj/docking_port/mobile/proc/admin_fly_shuttle(mob/user) var/list/options = list() diff --git a/code/modules/admin/verbs/spawnobjasmob.dm b/code/modules/admin/verbs/spawnobjasmob.dm index 924c9885713..e673202f0ba 100644 --- a/code/modules/admin/verbs/spawnobjasmob.dm +++ b/code/modules/admin/verbs/spawnobjasmob.dm @@ -1,11 +1,4 @@ -/datum/admins/proc/spawn_objasmob(object as text) - set category = "Debug" - set desc = "(obj path) Spawn object-mob" - set name = "Spawn object-mob" - - if(!check_rights(R_SPAWN)) - return - +ADMIN_VERB(spawn_obj_as_mob, R_SPAWN, "Spawn Object-Mob", "Spawn an object as if it were a mob.", ADMIN_CATEGORY_DEBUG, object as text) var/chosen = pick_closest_path(object, make_types_fancy(subtypesof(/obj))) if (!chosen) @@ -15,21 +8,63 @@ var/obj/chosen_obj = text2path(chosen) - var/list/settings = list( - "mainsettings" = list( - "name" = list("desc" = "Name", "type" = "string", "value" = "Bob"), - "maxhealth" = list("desc" = "Max. health", "type" = "number", "value" = 100), - "access" = list("desc" = "Access ID", "type" = "datum", "path" = "/obj/item/card/id", "value" = "Default"), - "objtype" = list("desc" = "Base obj type", "type" = "datum", "path" = "/obj", "value" = "[chosen]"), - "googlyeyes" = list("desc" = "Googly eyes", "type" = "boolean", "value" = "No"), - "disableai" = list("desc" = "Disable AI", "type" = "boolean", "value" = "Yes"), - "idledamage" = list("desc" = "Damaged while idle", "type" = "boolean", "value" = "No"), - "dropitem" = list("desc" = "Drop obj on death", "type" = "boolean", "value" = "Yes"), - "mobtype" = list("desc" = "Base mob type", "type" = "datum", "path" = "/mob/living/simple_animal/hostile/mimic/copy", "value" = "/mob/living/simple_animal/hostile/mimic/copy"), - "ckey" = list("desc" = "ckey", "type" = "ckey", "value" = "none"), + var/list/settings = list("mainsettings" = list( + "name" = list( + "desc" = "Name", + "type" = "string", + "value" = "Bob", + ), + "maxhealth" = list( + "desc" = "Max. health", + "type" = "number", + "value" = 100, + ), + "access" = list( + "desc" = "Access ID", + "type" = "datum", + "path" = "/obj/item/card/id", + "value" = "Default", + ), + "objtype" = list( + "desc" = "Base obj type", + "type" = "datum", + "path" = "/obj", + "value" = "[chosen]", + ), + "googlyeyes" = list( + "desc" = "Googly eyes", + "type" = "boolean", + "value" = "No", + ), + "disableai" = list( + "desc" = "Disable AI", + "type" = "boolean", + "value" = "Yes", + ), + "idledamage" = list( + "desc" = "Damaged while idle", + "type" = "boolean", + "value" = "No", + ), + "dropitem" = list( + "desc" = "Drop obj on death", + "type" = "boolean", + "value" = "Yes", + ), + "mobtype" = list( + "desc" = "Base mob type", + "type" = "datum", + "path" = "/mob/living/simple_animal/hostile/mimic/copy", + "value" = "/mob/living/simple_animal/hostile/mimic/copy", + ), + "ckey" = list( + "desc" = "ckey", + "type" = "ckey", + "value" = "none", + ), )) - var/list/prefreturn = presentpreflikepicker(usr,"Customize mob", "Customize mob", Button1="Ok", width = 450, StealFocus = 1,Timeout = 0, settings=settings) + var/list/prefreturn = presentpreflikepicker(user.mob,"Customize mob", "Customize mob", Button1="Ok", width = 450, StealFocus = 1,Timeout = 0, settings=settings) if (prefreturn["button"] == 1) settings = prefreturn["settings"] var/mainsettings = settings["mainsettings"] @@ -37,9 +72,9 @@ basemob = text2path(mainsettings["mobtype"]["value"]) if (!ispath(basemob, /mob/living/simple_animal/hostile/mimic/copy) || !ispath(chosen_obj, /obj)) - to_chat(usr, "Mob or object path invalid", confidential = TRUE) + to_chat(user.mob, "Mob or object path invalid", confidential = TRUE) - basemob = new basemob(get_turf(usr), new chosen_obj(get_turf(usr)), usr, mainsettings["dropitem"]["value"] == "Yes" ? FALSE : TRUE, (mainsettings["googlyeyes"]["value"] == "Yes" ? FALSE : TRUE)) + basemob = new basemob(get_turf(user.mob), new chosen_obj(get_turf(user.mob)), user.mob, mainsettings["dropitem"]["value"] == "Yes" ? FALSE : TRUE, (mainsettings["googlyeyes"]["value"] == "Yes" ? FALSE : TRUE)) if (mainsettings["disableai"]["value"] == "Yes") basemob.toggle_ai(AI_OFF) @@ -65,5 +100,5 @@ basemob.ckey = mainsettings["ckey"]["value"] - log_admin("[key_name(usr)] spawned a sentient object-mob [basemob] from [chosen_obj] at [AREACOORD(usr)]") + log_admin("[key_name(user.mob)] spawned a sentient object-mob [basemob] from [chosen_obj] at [AREACOORD(user.mob)]") BLACKBOX_LOG_ADMIN_VERB("Spawn object-mob") diff --git a/code/modules/admin/verbs/special_verbs.dm b/code/modules/admin/verbs/special_verbs.dm new file mode 100644 index 00000000000..309c14d4455 --- /dev/null +++ b/code/modules/admin/verbs/special_verbs.dm @@ -0,0 +1,43 @@ +// Admin Verbs in this file are special and cannot use the AVD system for some reason or another. + +/client/proc/show_verbs() + set name = "Adminverbs - Show" + set category = ADMIN_CATEGORY_MAIN + + remove_verb(src, /client/proc/show_verbs) + add_admin_verbs() + + to_chat(src, span_interface("All of your adminverbs are now visible."), confidential = TRUE) + BLACKBOX_LOG_ADMIN_VERB("Show Adminverbs") + +/client/proc/readmin() + set name = "Readmin" + set category = "Admin" + set desc = "Regain your admin powers." + + var/datum/admins/A = GLOB.deadmins[ckey] + + if(!A) + A = GLOB.admin_datums[ckey] + if (!A) + var/msg = " is trying to readmin but they have no deadmin entry" + message_admins("[key_name_admin(src)][msg]") + log_admin_private("[key_name(src)][msg]") + return + + A.associate(src) + + if (!holder) + return //This can happen if an admin attempts to vv themself into somebody elses's deadmin datum by getting ref via brute force + + to_chat(src, span_interface("You are now an admin."), confidential = TRUE) + message_admins("[src] re-adminned themselves.") + log_admin("[src] re-adminned themselves.") + BLACKBOX_LOG_ADMIN_VERB("Readmin") + +/client/proc/admin_2fa_verify() + set name = "Verify Admin" + set category = "Admin" + + var/datum/admins/admin = GLOB.admin_datums[ckey] + admin?.associate(src) diff --git a/code/modules/admin/view_variables/mark_datum.dm b/code/modules/admin/view_variables/mark_datum.dm index 44c3b2b83b2..1d9dd3a1a37 100644 --- a/code/modules/admin/view_variables/mark_datum.dm +++ b/code/modules/admin/view_variables/mark_datum.dm @@ -8,10 +8,8 @@ holder.RegisterSignal(holder.marked_datum, COMSIG_QDELETING, TYPE_PROC_REF(/datum/admins, handle_marked_del)) vv_update_display(D, "marked", VV_MSG_MARKED) -/client/proc/mark_datum_mapview(datum/D as mob|obj|turf|area in view(view)) - set category = "Debug" - set name = "Mark Object" - mark_datum(D) +ADMIN_VERB_ONLY_CONTEXT_MENU(mark_datum, R_NONE, "Mark Object", datum/target as mob|obj|turf|area in view()) + user.mark_datum(target) /datum/admins/proc/handle_marked_del(datum/source) SIGNAL_HANDLER diff --git a/code/modules/admin/view_variables/tag_datum.dm b/code/modules/admin/view_variables/tag_datum.dm index 3b611e3cdf9..b4ca42860c3 100644 --- a/code/modules/admin/view_variables/tag_datum.dm +++ b/code/modules/admin/view_variables/tag_datum.dm @@ -12,7 +12,5 @@ else holder.add_tagged_datum(target_datum) -/client/proc/tag_datum_mapview(datum/target_datum as mob|obj|turf|area in view(view)) - set category = "Debug" - set name = "Tag Datum" - tag_datum(target_datum) +ADMIN_VERB_ONLY_CONTEXT_MENU(tag_datum, R_NONE, "Tag Datum", datum/target_datum as mob|obj|turf|area in view()) + user.tag_datum(target_datum) diff --git a/code/modules/admin/view_variables/topic_basic.dm b/code/modules/admin/view_variables/topic_basic.dm index 8a27d342578..4f363653127 100644 --- a/code/modules/admin/view_variables/topic_basic.dm +++ b/code/modules/admin/view_variables/topic_basic.dm @@ -140,6 +140,7 @@ return var/datum/greyscale_modify_menu/menu = new(target, usr, SSgreyscale.configurations, unlocked = TRUE) menu.ui_interact(usr) - if(href_list[VV_HK_CALLPROC]) - usr.client.callproc_datum(target) + + if(href_list[VV_HK_CALLPROC]) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/call_proc_datum, target) diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm index 9f0d86e04f6..b139ec9d488 100644 --- a/code/modules/admin/view_variables/view_variables.dm +++ b/code/modules/admin/view_variables/view_variables.dm @@ -1,3 +1,7 @@ +ADMIN_VERB_AND_CONTEXT_MENU(debug_variables, R_NONE, "View Variables", "View the variables of a datum.", ADMIN_CATEGORY_DEBUG, datum/thing in world) + user.debug_variables(thing) + +// This is kept as a seperate proc because admins are able to show VV to non-admins /client/proc/debug_variables(datum/thing in world) set category = "Debug" set name = "View Variables" diff --git a/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm b/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm index 07e8dad2aa6..2fb5d526045 100644 --- a/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm +++ b/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm @@ -48,7 +48,7 @@ icon_state = "gizmo_scan" to_chat(user, span_notice("You switch the device to [mode == GIZMO_SCAN? "SCAN": "MARK"] MODE")) -/obj/item/abductor/gizmo/interact_with_atom(atom/interacting_with, mob/living/user) +/obj/item/abductor/gizmo/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!ScientistCheck(user)) return ITEM_INTERACT_SKIP_TO_ATTACK // So you slap them with it if(!console) @@ -110,7 +110,7 @@ icon_state = "silencer" inhand_icon_state = "gizmo" -/obj/item/abductor/silencer/interact_with_atom(atom/interacting_with, mob/living/user) +/obj/item/abductor/silencer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!AbductorCheck(user)) return ITEM_INTERACT_SKIP_TO_ATTACK // So you slap them with it @@ -285,8 +285,8 @@
    Congratulations! You are now trained for invasive xenobiology research!"} -/obj/item/paper/guides/antag/abductor/AltClick() - return //otherwise it would fold into a paperplane. +/obj/item/paper/guides/antag/abductor/click_alt() + return CLICK_ACTION_BLOCKING //otherwise it would fold into a paperplane. /obj/item/melee/baton/abductor name = "advanced baton" diff --git a/code/modules/antagonists/abductor/machinery/console.dm b/code/modules/antagonists/abductor/machinery/console.dm index 5bd5ce8c2ec..ee729de7068 100644 --- a/code/modules/antagonists/abductor/machinery/console.dm +++ b/code/modules/antagonists/abductor/machinery/console.dm @@ -198,11 +198,8 @@ pad.teleport_target = location to_chat(user, span_notice("Location marked as test subject release point.")) -/obj/machinery/abductor/console/Initialize(mapload) - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/abductor/console/LateInitialize() +/obj/machinery/abductor/console/post_machine_initialize() + . = ..() if(!team_number) return diff --git a/code/modules/antagonists/changeling/powers/pheromone_receptors.dm b/code/modules/antagonists/changeling/powers/pheromone_receptors.dm index 18fda4bf4ff..0e468159a3c 100644 --- a/code/modules/antagonists/changeling/powers/pheromone_receptors.dm +++ b/code/modules/antagonists/changeling/powers/pheromone_receptors.dm @@ -23,6 +23,9 @@ /datum/action/changeling/pheromone_receptors/sting_action(mob/living/carbon/user) ..() var/datum/antagonist/changeling/changeling = IS_CHANGELING(user) + if(HAS_TRAIT(user, TRAIT_ANOSMIA)) //Anosmia quirk holders can't smell anything + to_chat(user, span_warning("We can't smell!")) + return if(!receptors_active) to_chat(user, span_warning("We search for the scent of any nearby changelings.")) changeling.chem_recharge_slowdown += 0.25 diff --git a/code/modules/antagonists/cult/rune_spawn_action.dm b/code/modules/antagonists/cult/rune_spawn_action.dm index af4350427b5..3d791dbce44 100644 --- a/code/modules/antagonists/cult/rune_spawn_action.dm +++ b/code/modules/antagonists/cult/rune_spawn_action.dm @@ -42,7 +42,7 @@ var/chosen_keyword if(initial(rune_type.req_keyword)) chosen_keyword = tgui_input_text(owner, "Enter a keyword for the new rune.", "Words of Power", max_length = MAX_NAME_LEN) - if(!chosen_keyword) + if(!chosen_keyword || !turf_check(T)) return //the outer ring is always the same across all runes var/obj/effect/temp_visual/cult/rune_spawn/R1 = new(T, scribe_time, rune_color) diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index aa979ff7814..cc4a80d980f 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -491,7 +491,7 @@ structure_check() searches for nearby cultist structures required for the invoca fail_invoke() return var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to? - if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated() || !actual_selected_rune) + if(!Adjacent(user) || QDELETED(src) || user.incapacitated() || !actual_selected_rune) fail_invoke() return diff --git a/code/modules/antagonists/disease/disease_datum.dm b/code/modules/antagonists/disease/disease_datum.dm index 9d5af7ab83e..17364feec55 100644 --- a/code/modules/antagonists/disease/disease_datum.dm +++ b/code/modules/antagonists/disease/disease_datum.dm @@ -54,7 +54,7 @@ result += objectives_text - var/special_role_text = lowertext(name) + var/special_role_text = LOWER_TEXT(name) if(win) result += span_greentext("The [special_role_text] was successful!") diff --git a/code/modules/antagonists/heretic/items/forbidden_book.dm b/code/modules/antagonists/heretic/items/forbidden_book.dm index ad6bc388800..06f091c77e7 100644 --- a/code/modules/antagonists/heretic/items/forbidden_book.dm +++ b/code/modules/antagonists/heretic/items/forbidden_book.dm @@ -39,11 +39,11 @@ if(book_open) close_animation() RemoveElement(/datum/element/heretic_focus) - w_class = WEIGHT_CLASS_SMALL + update_weight_class(WEIGHT_CLASS_SMALL) else open_animation() AddElement(/datum/element/heretic_focus) - w_class = WEIGHT_CLASS_NORMAL + update_weight_class(WEIGHT_CLASS_NORMAL) /obj/item/codex_cicatrix/afterattack(atom/target, mob/user, proximity_flag, click_parameters) . = ..() diff --git a/code/modules/antagonists/malf_ai/malf_ai.dm b/code/modules/antagonists/malf_ai/malf_ai.dm index dbaec3e3a20..095ccbc1b75 100644 --- a/code/modules/antagonists/malf_ai/malf_ai.dm +++ b/code/modules/antagonists/malf_ai/malf_ai.dm @@ -267,7 +267,7 @@ // SKYRAT EDIT REMOVAL START /* - var/special_role_text = lowertext(name) + var/special_role_text = LOWER_TEXT(name) if(malf_ai_won) result += span_greentext("The [special_role_text] was successful!") diff --git a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm index 2b323d51162..04ebab73cbd 100644 --- a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm +++ b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm @@ -232,7 +232,7 @@ pad_ref = WEAKREF(I.buffer) return TRUE -/obj/machinery/computer/piratepad_control/LateInitialize() +/obj/machinery/computer/piratepad_control/post_machine_initialize() . = ..() if(cargo_hold_id) for(var/obj/machinery/piratepad/P as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/piratepad)) diff --git a/code/modules/antagonists/spy/spy.dm b/code/modules/antagonists/spy/spy.dm index e0ea7e40754..89809958b29 100644 --- a/code/modules/antagonists/spy/spy.dm +++ b/code/modules/antagonists/spy/spy.dm @@ -130,7 +130,30 @@ your_mission.owner = owner your_mission.explanation_text = pick_list_replacements(SPY_OBJECTIVE_FILE, "objective_body") objectives += your_mission - + + if((length(objectives) < 3) && prob(25)) + switch(rand(1, 4)) + if(1) + var/datum/objective/protect/save_the_person = new() + save_the_person.owner = owner + save_the_person.no_failure = TRUE + objectives += save_the_person + if(2) + var/datum/objective/protect/nonhuman/save_the_entity = new() + save_the_entity.owner = owner + save_the_entity.no_failure = TRUE + objectives += save_the_entity + if(3) + var/datum/objective/jailbreak/save_the_jailbird = new() + save_the_jailbird.owner = owner + save_the_jailbird.no_failure = TRUE + objectives += save_the_jailbird + if(4) + var/datum/objective/jailbreak/detain/cage_the_jailbird = new() + cage_the_jailbird.owner = owner + cage_the_jailbird.no_failure = TRUE + objectives += cage_the_jailbird + if(prob(10)) var/datum/objective/martyr/leave_no_trace = new() leave_no_trace.owner = owner @@ -141,6 +164,11 @@ steal_the_shuttle.owner = owner objectives += steal_the_shuttle + else if(prob(10)) //10% chance on 87.3% chance + var/datum/objective/exile/hit_the_bricks = new() + hit_the_bricks.owner = owner + objectives += hit_the_bricks + else var/datum/objective/escape/gtfo = new() gtfo.owner = owner diff --git a/code/modules/antagonists/traitor/balance_helper.dm b/code/modules/antagonists/traitor/balance_helper.dm index e78625ff1c1..b2a9661bfeb 100644 --- a/code/modules/antagonists/traitor/balance_helper.dm +++ b/code/modules/antagonists/traitor/balance_helper.dm @@ -1,11 +1,5 @@ -/client/proc/cmd_admin_debug_traitor_objectives() - set name = "Debug Traitor Objectives" - set category = "Debug" - - if(!check_rights(R_DEBUG)) - return - - SStraitor.traitor_debug_panel?.ui_interact(usr) +ADMIN_VERB(debug_traitor_objectives, R_DEBUG, "Debug Traitor Objectives", "Verify functionality of traitor goals.", ADMIN_CATEGORY_DEBUG) + SStraitor.traitor_debug_panel?.ui_interact(user.mob) /datum/traitor_objective_debug var/list/all_objectives diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 88776b6819a..5ad5aeecf26 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -360,7 +360,7 @@ result += contractor_round_end() result += "
    The traitor had a total of [DISPLAY_PROGRESSION(uplink_handler.progression_points)] Reputation and [uplink_handler.telecrystals] Unused Telecrystals." - var/special_role_text = lowertext(name) + var/special_role_text = LOWER_TEXT(name) if(traitor_won) result += span_greentext("The [special_role_text] was successful!") diff --git a/code/modules/antagonists/traitor/objectives/sabotage_machinery.dm b/code/modules/antagonists/traitor/objectives/sabotage_machinery.dm index 9723d2b653e..5a31c4c1739 100644 --- a/code/modules/antagonists/traitor/objectives/sabotage_machinery.dm +++ b/code/modules/antagonists/traitor/objectives/sabotage_machinery.dm @@ -49,7 +49,7 @@ GLOBAL_DATUM_INIT(objective_machine_handler, /datum/objective_target_machine_han for(var/obj/machinery/machine as anything in possible_machines) prepare_machine(machine) - replace_in_name("%JOB%", lowertext(chosen_job)) + replace_in_name("%JOB%", LOWER_TEXT(chosen_job)) replace_in_name("%MACHINE%", possible_machines[1].name) return TRUE diff --git a/code/modules/art/paintings.dm b/code/modules/art/paintings.dm index dd370f480f4..f050528bd3b 100644 --- a/code/modules/art/paintings.dm +++ b/code/modules/art/paintings.dm @@ -350,7 +350,7 @@ var/result = rustg_dmi_create_png(png_filename, "[width]", "[height]", image_data) if(result) CRASH("Error generating painting png : [result]") - painting_metadata.md5 = md5(lowertext(image_data)) + painting_metadata.md5 = md5(LOWER_TEXT(image_data)) generated_icon = new(png_filename) icon_generated = TRUE update_appearance() @@ -569,10 +569,12 @@ current_canvas = null update_appearance() -/obj/structure/sign/painting/AltClick(mob/user) - . = ..() - if(current_canvas?.can_select_frame(user)) - INVOKE_ASYNC(current_canvas, TYPE_PROC_REF(/obj/item/canvas, select_new_frame), user) +/obj/structure/sign/painting/click_alt(mob/user) + if(!current_canvas?.can_select_frame(user)) + return CLICK_ACTION_BLOCKING + + INVOKE_ASYNC(current_canvas, TYPE_PROC_REF(/obj/item/canvas, select_new_frame), user) + return CLICK_ACTION_SUCCESS /obj/structure/sign/painting/proc/frame_canvas(mob/user, obj/item/canvas/new_canvas) if(!(new_canvas.type in accepted_canvas_types)) @@ -663,7 +665,7 @@ stack_trace("Invalid persistence_id - [persistence_id]") return var/data = current_canvas.get_data_string() - var/md5 = md5(lowertext(data)) + var/md5 = md5(LOWER_TEXT(data)) var/list/current = SSpersistent_paintings.paintings[persistence_id] if(!current) current = list() diff --git a/code/modules/art/statues.dm b/code/modules/art/statues.dm index 428bb5d8e06..8ed46a5bf81 100644 --- a/code/modules/art/statues.dm +++ b/code/modules/art/statues.dm @@ -44,8 +44,6 @@ return return ..() -/obj/structure/statue/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation /obj/structure/statue/atom_deconstruct(disassembled = TRUE) var/amount_mod = disassembled ? 0 : -2 diff --git a/code/modules/assembly/health.dm b/code/modules/assembly/health.dm index 23c329894e7..28ab16f63d7 100644 --- a/code/modules/assembly/health.dm +++ b/code/modules/assembly/health.dm @@ -37,16 +37,14 @@ update_appearance() return secured -/obj/item/assembly/health/AltClick(mob/living/user) - if(!can_interact(user)) - return - +/obj/item/assembly/health/click_alt(mob/living/user) if(alarm_health == HEALTH_THRESHOLD_CRIT) alarm_health = HEALTH_THRESHOLD_DEAD to_chat(user, span_notice("You toggle [src] to \"detect death\" mode.")) else alarm_health = HEALTH_THRESHOLD_CRIT to_chat(user, span_notice("You toggle [src] to \"detect critical state\" mode.")) + return CLICK_ACTION_SUCCESS /obj/item/assembly/health/process() //not ready yet diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index 70f116b3e3e..5f50618e77d 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -141,8 +141,6 @@ return ..() -/obj/item/assembly_holder/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation /obj/item/assembly_holder/screwdriver_act(mob/user, obj/item/tool) if(..()) diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm index b5c847a78ab..8dd4573fcfd 100644 --- a/code/modules/assembly/infrared.dm +++ b/code/modules/assembly/infrared.dm @@ -35,8 +35,6 @@ buffer_turf = null return ..() -/obj/item/assembly/infra/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation /obj/item/assembly/infra/examine(mob/user) . = ..() diff --git a/code/modules/asset_cache/assets/arcade.dm b/code/modules/asset_cache/assets/arcade.dm index bcd23919f97..338b891190c 100644 --- a/code/modules/asset_cache/assets/arcade.dm +++ b/code/modules/asset_cache/assets/arcade.dm @@ -1,5 +1,7 @@ /datum/asset/simple/arcade assets = list( + "shopkeeper.png" = 'icons/ui_icons/arcade/shopkeeper.png', + "fireplace.png" = 'icons/ui_icons/arcade/fireplace.png', "boss1.gif" = 'icons/ui_icons/arcade/boss1.gif', "boss2.gif" = 'icons/ui_icons/arcade/boss2.gif', "boss3.gif" = 'icons/ui_icons/arcade/boss3.gif', diff --git a/code/modules/asset_cache/assets/icon_ref_map.dm b/code/modules/asset_cache/assets/icon_ref_map.dm new file mode 100644 index 00000000000..2f7f8463099 --- /dev/null +++ b/code/modules/asset_cache/assets/icon_ref_map.dm @@ -0,0 +1,28 @@ +/// Maps icon names to ref values +/datum/asset/json/icon_ref_map + name = "icon_ref_map" + early = TRUE + +/datum/asset/json/icon_ref_map/generate() + var/list/data = list() //"icons/obj/drinks.dmi" => "[0xc000020]" + + //var/start = "0xc000000" + var/value = 0 + + while(TRUE) + value += 1 + var/ref = "\[0xc[num2text(value,6,16)]\]" + var/mystery_meat = locate(ref) + + if(isicon(mystery_meat)) + if(!isfile(mystery_meat)) // Ignore the runtime icons for now + continue + var/path = get_icon_dmi_path(mystery_meat) //Try to get the icon path + if(path) + data[path] = ref + else if(mystery_meat) + continue; //Some other non-icon resource, ogg/json/whatever + else //Out of resources end this, could also try to end this earlier as soon as runtime generated icons appear but eh + break; + + return data diff --git a/code/modules/asset_cache/transports/asset_transport.dm b/code/modules/asset_cache/transports/asset_transport.dm index 19e40fb4884..3dbcc301843 100644 --- a/code/modules/asset_cache/transports/asset_transport.dm +++ b/code/modules/asset_cache/transports/asset_transport.dm @@ -82,11 +82,15 @@ /// asset_list - A list of asset filenames to be sent to the client. Can optionally be assoicated with the asset's asset_cache_item datum. /// Returns TRUE if any assets were sent. /datum/asset_transport/proc/send_assets(client/client, list/asset_list) +#if defined(UNIT_TESTS) + return +#endif + if (!istype(client)) if (ismob(client)) - var/mob/M = client - if (M.client) - client = M.client + var/mob/our_mob = client + if (our_mob.client) + client = our_mob.client else //no stacktrace because this will mainly happen because the client went away return else diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index d42618e9ee9..d152cf09e71 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -81,7 +81,7 @@ fire = 100 acid = 70 -/obj/machinery/atmospherics/LateInitialize() +/obj/machinery/atmospherics/post_machine_initialize() . = ..() update_name() @@ -607,11 +607,6 @@ animate(our_client, pixel_x = 0, pixel_y = 0, time = 0.05 SECONDS) our_client.move_delay = world.time + 0.05 SECONDS -/obj/machinery/atmospherics/AltClick(mob/living/L) - if(vent_movement & VENTCRAWL_ALLOWED && istype(L)) - L.handle_ventcrawl(src) - return - return ..() /** * Getter of a list of pipenets diff --git a/code/modules/atmospherics/machinery/bluespace_vendor.dm b/code/modules/atmospherics/machinery/bluespace_vendor.dm index 84753354018..91da04afaf2 100644 --- a/code/modules/atmospherics/machinery/bluespace_vendor.dm +++ b/code/modules/atmospherics/machinery/bluespace_vendor.dm @@ -71,7 +71,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/bluespace_vendor, 30) AddComponent(/datum/component/payment, tank_cost, SSeconomy.get_dep_account(ACCOUNT_ENG), PAYMENT_ANGRY) find_and_hang_on_wall( FALSE) -/obj/machinery/bluespace_vendor/LateInitialize() +/obj/machinery/bluespace_vendor/post_machine_initialize() . = ..() if(!map_spawned) return diff --git a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm index c06863ba092..fe6f9423b43 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm @@ -38,13 +38,15 @@ Passive gate is similar to the regular pump except: update_appearance() return ..() -/obj/machinery/atmospherics/components/binary/passive_gate/AltClick(mob/user) - if(can_interact(user)) - target_pressure = MAX_OUTPUT_PRESSURE - investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS) - balloon_alert(user, "pressure output set to [target_pressure] kPa") - update_appearance() - return ..() +/obj/machinery/atmospherics/components/binary/passive_gate/click_alt(mob/user) + if(target_pressure == MAX_OUTPUT_PRESSURE) + return CLICK_ACTION_BLOCKING + + target_pressure = MAX_OUTPUT_PRESSURE + investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS) + balloon_alert(user, "pressure output set to [target_pressure] kPa") + update_appearance() + return CLICK_ACTION_SUCCESS /obj/machinery/atmospherics/components/binary/passive_gate/update_icon_nopipes() cut_overlays() diff --git a/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm b/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm index 93192073275..c3313322135 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/pressure_valve.dm @@ -30,13 +30,15 @@ update_appearance() return ..() -/obj/machinery/atmospherics/components/binary/pressure_valve/AltClick(mob/user) - if(can_interact(user)) - target_pressure = MAX_OUTPUT_PRESSURE - investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS) - balloon_alert(user, "target pressure set to [target_pressure] kPa") - update_appearance() - return ..() +/obj/machinery/atmospherics/components/binary/pressure_valve/click_alt(mob/user) + if(target_pressure == MAX_OUTPUT_PRESSURE) + return CLICK_ACTION_BLOCKING + + target_pressure = MAX_OUTPUT_PRESSURE + investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS) + balloon_alert(user, "target pressure set to [target_pressure] kPa") + update_appearance() + return CLICK_ACTION_SUCCESS /obj/machinery/atmospherics/components/binary/pressure_valve/update_icon_nopipes() if(on && is_operational && is_gas_flowing) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm index 3c1ba634cae..035f3a0f996 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm @@ -43,13 +43,15 @@ update_appearance() return ..() -/obj/machinery/atmospherics/components/binary/pump/AltClick(mob/user) - if(can_interact(user)) - target_pressure = MAX_OUTPUT_PRESSURE - investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS) - balloon_alert(user, "pressure output set to [target_pressure] kPa") - update_appearance() - return ..() +/obj/machinery/atmospherics/components/binary/pump/click_alt(mob/user) + if(target_pressure == MAX_OUTPUT_PRESSURE) + return CLICK_ACTION_BLOCKING + + target_pressure = MAX_OUTPUT_PRESSURE + investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS) + balloon_alert(user, "pressure output set to [target_pressure] kPa") + update_appearance() + return CLICK_ACTION_SUCCESS /obj/machinery/atmospherics/components/binary/pump/update_icon_nopipes() icon_state = (on && is_operational) ? "pump_on-[set_overlay_offset(piping_layer)]" : "pump_off-[set_overlay_offset(piping_layer)]" diff --git a/code/modules/atmospherics/machinery/components/binary_devices/temperature_gate.dm b/code/modules/atmospherics/machinery/components/binary_devices/temperature_gate.dm index bbe788bac53..d1202dbec94 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/temperature_gate.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/temperature_gate.dm @@ -35,13 +35,15 @@ update_appearance() return ..() -/obj/machinery/atmospherics/components/binary/temperature_gate/AltClick(mob/user) - if(can_interact(user)) - target_temperature = max_temperature - investigate_log("was set to [target_temperature] K by [key_name(user)]", INVESTIGATE_ATMOS) - balloon_alert(user, "target temperature set to [target_temperature] K") - update_appearance() - return ..() +/obj/machinery/atmospherics/components/binary/temperature_gate/click_alt(mob/user) + if(target_temperature == max_temperature) + return CLICK_ACTION_BLOCKING + + target_temperature = max_temperature + investigate_log("was set to [target_temperature] K by [key_name(user)]", INVESTIGATE_ATMOS) + balloon_alert(user, "target temperature set to [target_temperature] K") + update_appearance() + return CLICK_ACTION_SUCCESS /obj/machinery/atmospherics/components/binary/temperature_gate/examine(mob/user) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm index 0fdb5aca6a3..2615b964ed8 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/temperature_pump.dm @@ -30,13 +30,15 @@ update_appearance() return ..() -/obj/machinery/atmospherics/components/binary/temperature_pump/AltClick(mob/user) - if(can_interact(user) && !(heat_transfer_rate == max_heat_transfer_rate)) - heat_transfer_rate = max_heat_transfer_rate - investigate_log("was set to [heat_transfer_rate]% by [key_name(user)]", INVESTIGATE_ATMOS) - balloon_alert(user, "transfer rate set to [heat_transfer_rate]%") - update_appearance() - return ..() +/obj/machinery/atmospherics/components/binary/temperature_pump/click_alt(mob/user) + if(heat_transfer_rate == max_heat_transfer_rate) + return CLICK_ACTION_BLOCKING + + heat_transfer_rate = max_heat_transfer_rate + investigate_log("was set to [heat_transfer_rate]% by [key_name(user)]", INVESTIGATE_ATMOS) + balloon_alert(user, "transfer rate set to [heat_transfer_rate]%") + update_appearance() + return CLICK_ACTION_SUCCESS /obj/machinery/atmospherics/components/binary/temperature_pump/update_icon_nopipes() icon_state = "tpump_[on && is_operational ? "on" : "off"]-[set_overlay_offset(piping_layer)]" diff --git a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm index 139cbe71b36..41dc549b858 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm @@ -41,13 +41,15 @@ update_appearance() return ..() -/obj/machinery/atmospherics/components/binary/volume_pump/AltClick(mob/user) - if(can_interact(user)) - transfer_rate = MAX_TRANSFER_RATE - investigate_log("was set to [transfer_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS) - balloon_alert(user, "volume output set to [transfer_rate] L/s") - update_appearance() - return ..() +/obj/machinery/atmospherics/components/binary/volume_pump/click_alt(mob/user) + if(transfer_rate == MAX_TRANSFER_RATE) + return CLICK_ACTION_BLOCKING + + transfer_rate = MAX_TRANSFER_RATE + investigate_log("was set to [transfer_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS) + balloon_alert(user, "volume output set to [transfer_rate] L/s") + update_appearance() + return CLICK_ACTION_SUCCESS /obj/machinery/atmospherics/components/binary/volume_pump/update_icon_nopipes() icon_state = on && is_operational ? "volpump_on-[set_overlay_offset(piping_layer)]" : "volpump_off-[set_overlay_offset(piping_layer)]" diff --git a/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer.dm b/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer.dm index 0ab8427c0ae..56ee3c6039d 100644 --- a/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer.dm +++ b/code/modules/atmospherics/machinery/components/electrolyzer/electrolyzer.dm @@ -187,14 +187,12 @@ return return ..() -/obj/machinery/electrolyzer/AltClick(mob/user) - . = ..() +/obj/machinery/electrolyzer/click_alt(mob/user) if(panel_open) balloon_alert(user, "close panel!") - return - if(!can_interact(user)) - return + return CLICK_ACTION_BLOCKING toggle_power(user) + return CLICK_ACTION_SUCCESS /obj/machinery/electrolyzer/proc/toggle_power(mob/user) if(!anchored && !cell) diff --git a/code/modules/atmospherics/machinery/components/tank.dm b/code/modules/atmospherics/machinery/components/tank.dm index 8df616c179c..a9fcaf93ec6 100644 --- a/code/modules/atmospherics/machinery/components/tank.dm +++ b/code/modules/atmospherics/machinery/components/tank.dm @@ -104,7 +104,7 @@ // We late initialize here so all stationary tanks have time to set up their // initial gas mixes and signal registrations. -/obj/machinery/atmospherics/components/tank/LateInitialize() +/obj/machinery/atmospherics/components/tank/post_machine_initialize() . = ..() GetMergeGroup(merger_id, merger_typecache) diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm index 1727d4877b5..c6b4bd43be4 100644 --- a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm +++ b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm @@ -32,13 +32,15 @@ update_appearance() return ..() -/obj/machinery/atmospherics/components/trinary/filter/AltClick(mob/user) - if(can_interact(user)) - transfer_rate = MAX_TRANSFER_RATE - investigate_log("was set to [transfer_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS) - balloon_alert(user, "volume output set to [transfer_rate] L/s") - update_appearance() - return ..() +/obj/machinery/atmospherics/components/trinary/filter/click_alt(mob/user) + if(transfer_rate == MAX_TRANSFER_RATE) + return CLICK_ACTION_BLOCKING + + transfer_rate = MAX_TRANSFER_RATE + investigate_log("was set to [transfer_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS) + balloon_alert(user, "volume output set to [transfer_rate] L/s") + update_appearance() + return CLICK_ACTION_SUCCESS /obj/machinery/atmospherics/components/trinary/filter/update_overlays() . = ..() diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm index 862fbc65c89..f832adcb4ea 100644 --- a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm +++ b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm @@ -35,13 +35,15 @@ update_appearance() return ..() -/obj/machinery/atmospherics/components/trinary/mixer/AltClick(mob/user) - if(can_interact(user)) - target_pressure = MAX_OUTPUT_PRESSURE - investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS) - balloon_alert(user, "pressure output on set to [target_pressure] kPa") - update_appearance() - return ..() +/obj/machinery/atmospherics/components/trinary/mixer/click_alt(mob/user) + if(target_pressure == MAX_OUTPUT_PRESSURE) + return CLICK_ACTION_BLOCKING + + target_pressure = MAX_OUTPUT_PRESSURE + investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS) + balloon_alert(user, "pressure output on set to [target_pressure] kPa") + update_appearance() + return CLICK_ACTION_SUCCESS /obj/machinery/atmospherics/components/trinary/mixer/update_overlays() . = ..() diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 71610f05f40..ac88174dbc4 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -645,14 +645,13 @@ balloon_alert(user, "turned [on ? "on" : "off"]") return ..() -/obj/machinery/cryo_cell/AltClick(mob/user) - if(can_interact(user)) - if(state_open) - close_machine() - else - open_machine() - balloon_alert(user, "door [state_open ? "opened" : "closed"]") - return ..() +/obj/machinery/cryo_cell/click_alt(mob/user) + if(state_open) + close_machine() + else + open_machine() + balloon_alert(user, "door [state_open ? "opened" : "closed"]") + return CLICK_ACTION_SUCCESS /obj/machinery/cryo_cell/get_remote_view_fullscreens(mob/user) user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1) 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 4161a30ed7d..771301b60e4 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm @@ -62,13 +62,15 @@ update_appearance() return ..() -/obj/machinery/atmospherics/components/unary/outlet_injector/AltClick(mob/user) - if(can_interact(user)) - volume_rate = MAX_TRANSFER_RATE - investigate_log("was set to [volume_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS) - balloon_alert(user, "volume output set to [volume_rate] L/s") - update_appearance() - return ..() +/obj/machinery/atmospherics/components/unary/outlet_injector/click_alt(mob/user) + if(volume_rate == MAX_TRANSFER_RATE) + return CLICK_ACTION_BLOCKING + + volume_rate = MAX_TRANSFER_RATE + investigate_log("was set to [volume_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS) + balloon_alert(user, "volume output set to [volume_rate] L/s") + update_appearance() + return CLICK_ACTION_SUCCESS /obj/machinery/atmospherics/components/unary/outlet_injector/update_icon_nopipes() cut_overlays() 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 17f6c761f12..4ac0e959e40 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm @@ -12,6 +12,8 @@ pipe_state = "pvent" has_cap_visuals = TRUE vent_movement = VENTCRAWL_ALLOWED | VENTCRAWL_CAN_SEE | VENTCRAWL_ENTRANCE_ALLOWED + interaction_flags_click = NEED_VENTCRAWL + /obj/machinery/atmospherics/components/unary/passive_vent/update_icon_nopipes() cut_overlays() diff --git a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm index 0af962ac0f3..01def672bf7 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm @@ -144,12 +144,10 @@ . += span_notice("Heat capacity at [heat_capacity] Joules per Kelvin.") . += span_notice("Temperature range [min_temperature]K - [max_temperature]K ([(T0C-min_temperature)*-1]C - [(T0C-max_temperature)*-1]C).") -/obj/machinery/atmospherics/components/unary/thermomachine/AltClick(mob/living/user) +/obj/machinery/atmospherics/components/unary/thermomachine/click_alt(mob/living/user) if(panel_open) balloon_alert(user, "close panel!") - return - if(!can_interact(user)) - return + return CLICK_ACTION_BLOCKING if(target_temperature == T20C) target_temperature = max_temperature @@ -161,6 +159,7 @@ investigate_log("was set to [target_temperature] K by [key_name(user)]", INVESTIGATE_ATMOS) balloon_alert(user, "temperature reset to [target_temperature] K") update_appearance() + return CLICK_ACTION_SUCCESS /// Performs heat calculation for the freezer. /// We just equalize the gasmix with an object at temp = var/target_temperature and heat cap = var/heat_capacity diff --git a/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm b/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm index 4d876fd4586..c8bfd8628e9 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm @@ -17,6 +17,12 @@ ..() update_appearance() + +/obj/machinery/atmospherics/components/unary/click_alt(mob/living/beno) + beno.handle_ventcrawl(src) + return CLICK_ACTION_SUCCESS + + /obj/machinery/atmospherics/components/unary/proc/assign_uid_vents() uid = num2text(gl_uid++) return uid 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 e49dc3e62d3..330e00edfd3 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm @@ -18,6 +18,7 @@ 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 + interaction_flags_click = NEED_VENTCRAWL ///Direction of pumping the gas (ATMOS_DIRECTION_RELEASING or ATMOS_DIRECTION_SIPHONING) var/pump_direction = ATMOS_DIRECTION_RELEASING 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 54704dcb5b6..0871053106f 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm @@ -15,6 +15,7 @@ has_cap_visuals = TRUE vent_movement = VENTCRAWL_ALLOWED | VENTCRAWL_CAN_SEE | VENTCRAWL_ENTRANCE_ALLOWED processing_flags = NONE + interaction_flags_click = NEED_VENTCRAWL ///The mode of the scrubber (ATMOS_DIRECTION_SCRUBBING or ATMOS_DIRECTION_SIPHONING) var/scrubbing = ATMOS_DIRECTION_SCRUBBING diff --git a/code/modules/atmospherics/machinery/other/meter.dm b/code/modules/atmospherics/machinery/other/meter.dm index ee1d052b7ed..97bff1ddaea 100644 --- a/code/modules/atmospherics/machinery/other/meter.dm +++ b/code/modules/atmospherics/machinery/other/meter.dm @@ -22,7 +22,9 @@ /obj/machinery/meter/Destroy() SSair.stop_processing_machine(src) - target = null + if(!isnull(target)) + UnregisterSignal(target, COMSIG_QDELETING) + target = null return ..() /obj/machinery/meter/Initialize(mapload, new_piping_layer) @@ -45,8 +47,14 @@ candidate = pipe if(candidate) target = candidate + RegisterSignal(target, COMSIG_QDELETING, PROC_REF(drop_meter)) setAttachLayer(candidate.piping_layer) +///Called when the parent pipe is removed +/obj/machinery/meter/proc/drop_meter() + SIGNAL_HANDLER + deconstruct(FALSE) + /obj/machinery/meter/proc/setAttachLayer(new_layer) target_layer = new_layer PIPING_LAYER_DOUBLE_SHIFT(src, target_layer) @@ -135,7 +143,8 @@ return TRUE /obj/machinery/meter/on_deconstruction(disassembled) - new /obj/item/pipe_meter(loc) + var/obj/item/pipe_meter/meter_object = new /obj/item/pipe_meter(get_turf(src)) + transfer_fingerprints_to(meter_object) /obj/machinery/meter/interact(mob/user) if(machine_stat & (NOPOWER|BROKEN)) diff --git a/code/modules/atmospherics/machinery/pipes/pipe_spritesheet_helper.dm b/code/modules/atmospherics/machinery/pipes/pipe_spritesheet_helper.dm index 6b1997cc3c7..75c85d2a665 100644 --- a/code/modules/atmospherics/machinery/pipes/pipe_spritesheet_helper.dm +++ b/code/modules/atmospherics/machinery/pipes/pipe_spritesheet_helper.dm @@ -1,7 +1,4 @@ -/client/proc/GeneratePipeSpritesheet() - set name = "Generate Pipe Spritesheet" - set category = "Debug" - +ADMIN_VERB(generate_pipe_spritesheet, R_DEBUG, "Generate Pipe Spritesheet", "Generates the pipe spritesheets.", ADMIN_CATEGORY_DEBUG) var/datum/pipe_icon_generator/generator = new generator.Start() fcopy(generator.generated_icons, "icons/obj/pipes_n_cables/!pipes_bitmask.dmi") diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm index c0dc18c0e8e..574daa2af3a 100644 --- a/code/modules/atmospherics/machinery/pipes/pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/pipes.dm @@ -34,18 +34,13 @@ if(hide) AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) //if changing this, change the subtypes RemoveElements too, because thats how bespoke works -/obj/machinery/atmospherics/pipe/Destroy() - QDEL_NULL(parent) - +/obj/machinery/atmospherics/pipe/on_deconstruction(disassembled) releaseAirToTurf() - var/turf/local_turf = loc - for(var/obj/machinery/meter/meter in local_turf) - if(meter.target != src) - continue - var/obj/item/pipe_meter/meter_object = new (local_turf) - meter.transfer_fingerprints_to(meter_object) - qdel(meter) + return ..() + +/obj/machinery/atmospherics/pipe/Destroy() + QDEL_NULL(parent) return ..() //----------------- diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm index 389de6e3701..3713958fbaa 100644 --- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm +++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm @@ -8,6 +8,7 @@ armor_type = /datum/armor/machinery_portable_atmospherics anchored = FALSE layer = ABOVE_OBJ_LAYER + interaction_flags_click = NEED_DEXTERITY ///Stores the gas mixture of the portable component. Don't access this directly, use return_air() so you support the temporary processing it provides var/datum/gas_mixture/air_contents @@ -46,14 +47,17 @@ AddElement(/datum/element/climbable, climb_time = 3 SECONDS, climb_stun = 3 SECONDS) AddElement(/datum/element/elevation, pixel_shift = 8) +/obj/machinery/portable_atmospherics/on_deconstruction(disassembled) + if(nob_crystal_inserted) + new /obj/item/hypernoblium_crystal(src) + + return ..() + /obj/machinery/portable_atmospherics/Destroy() disconnect() air_contents = null SSair.stop_processing_machine(src) - if(nob_crystal_inserted) - new /obj/item/hypernoblium_crystal(src) - return ..() /obj/machinery/portable_atmospherics/examine(mob/user) @@ -159,14 +163,12 @@ update_appearance() return TRUE -/obj/machinery/portable_atmospherics/AltClick(mob/living/user) - . = ..() - if(!istype(user) || !user.can_perform_action(src, NEED_DEXTERITY) || !can_interact(user)) - return +/obj/machinery/portable_atmospherics/click_alt(mob/living/user) if(!holding) - return + return CLICK_ACTION_BLOCKING to_chat(user, span_notice("You remove [holding] from [src].")) replace_tank(user, TRUE) + return CLICK_ACTION_SUCCESS /obj/machinery/portable_atmospherics/examine(mob/user) . = ..() diff --git a/code/modules/atmospherics/machinery/portable/pump.dm b/code/modules/atmospherics/machinery/portable/pump.dm index e7dfc229a39..7b0dbef314e 100644 --- a/code/modules/atmospherics/machinery/portable/pump.dm +++ b/code/modules/atmospherics/machinery/portable/pump.dm @@ -12,7 +12,7 @@ volume = 1000 -/obj/machinery/portable_atmospherics/pump/Destroy() +/obj/machinery/portable_atmospherics/pump/on_deconstruction(disassembled) var/turf/local_turf = get_turf(src) local_turf.assume_air(air_contents) return ..() diff --git a/code/modules/atmospherics/machinery/portable/scrubber.dm b/code/modules/atmospherics/machinery/portable/scrubber.dm index 576dff39a8d..336cdc4829f 100644 --- a/code/modules/atmospherics/machinery/portable/scrubber.dm +++ b/code/modules/atmospherics/machinery/portable/scrubber.dm @@ -31,9 +31,9 @@ /datum/gas/halon, ) -/obj/machinery/portable_atmospherics/scrubber/Destroy() - var/turf/T = get_turf(src) - T.assume_air(air_contents) +/obj/machinery/portable_atmospherics/scrubber/on_deconstruction(disassembled) + var/turf/local_turf = get_turf(src) + local_turf.assume_air(air_contents) return ..() /obj/machinery/portable_atmospherics/scrubber/update_icon_state() diff --git a/code/modules/awaymissions/mission_code/murderdome.dm b/code/modules/awaymissions/mission_code/murderdome.dm index 520372e68ac..a59a491d492 100644 --- a/code/modules/awaymissions/mission_code/murderdome.dm +++ b/code/modules/awaymissions/mission_code/murderdome.dm @@ -1,20 +1,27 @@ /obj/structure/window/reinforced/fulltile/indestructible name = "robust window" - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION flags_1 = PREVENT_CLICK_UNDER_1 resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF -/obj/structure/window/reinforced/fulltile/indestructible/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - return FALSE +/obj/structure/window/reinforced/fulltile/indestructible/screwdriver_act(mob/living/user, obj/item/tool) + return NONE +/obj/structure/window/reinforced/fulltile/indestructible/wrench_act(mob/living/user, obj/item/tool) + return NONE + +/obj/structure/window/reinforced/fulltile/indestructible/crowbar_act(mob/living/user, obj/item/tool) + return NONE /obj/structure/grille/indestructible - obj_flags = CONDUCTS_ELECTRICITY | NO_DECONSTRUCTION + obj_flags = CONDUCTS_ELECTRICITY resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF -/obj/structure/grille/indestructible/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - return FALSE +/obj/structure/grille/indestructible/screwdriver_act(mob/living/user, obj/item/tool) + return NONE + +/obj/structure/grille/indestructible/wirecutter_act(mob/living/user, obj/item/tool) + return NONE /obj/effect/spawner/structure/window/reinforced/indestructible spawn_list = list(/obj/structure/grille/indestructible, /obj/structure/window/reinforced/fulltile/indestructible) diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm index 2b8d4e80663..cc35b4a79ef 100644 --- a/code/modules/awaymissions/mission_code/snowdin.dm +++ b/code/modules/awaymissions/mission_code/snowdin.dm @@ -369,7 +369,7 @@ /obj/structure/barricade/wooden/snowed name = "crude plank barricade" desc = "This space is blocked off by a wooden barricade. It seems to be covered in a layer of snow." - icon_state = "woodenbarricade-snow" + icon_state = "woodenbarricade_snow" max_integrity = 125 /obj/item/clothing/under/syndicate/coldres diff --git a/code/modules/awaymissions/zlevel.dm b/code/modules/awaymissions/zlevel.dm index c4bb2d17610..0fdc5093511 100644 --- a/code/modules/awaymissions/zlevel.dm +++ b/code/modules/awaymissions/zlevel.dm @@ -62,10 +62,10 @@ GLOBAL_LIST_INIT(potentialConfigRandomZlevels, generate_map_list_from_directory( var/name = null if (pos) - name = lowertext(copytext(t, 1, pos)) + name = LOWER_TEXT(copytext(t, 1, pos)) else - name = lowertext(t) + name = LOWER_TEXT(t) if (!name) continue diff --git a/code/modules/bitrunning/objects/byteforge.dm b/code/modules/bitrunning/objects/byteforge.dm index f8212b7666b..b971cdae75d 100644 --- a/code/modules/bitrunning/objects/byteforge.dm +++ b/code/modules/bitrunning/objects/byteforge.dm @@ -14,7 +14,7 @@ return INITIALIZE_HINT_LATELOAD -/obj/machinery/byteforge/LateInitialize() +/obj/machinery/byteforge/post_machine_initialize() . = ..() setup_particles() diff --git a/code/modules/bitrunning/objects/disks.dm b/code/modules/bitrunning/objects/disks.dm index d6b44a60518..6e166d5eb7f 100644 --- a/code/modules/bitrunning/objects/disks.dm +++ b/code/modules/bitrunning/objects/disks.dm @@ -48,7 +48,7 @@ names += initial(thing.name) var/choice = tgui_input_list(user, message = "Select an ability", title = "Bitrunning Program", items = names) - if(isnull(choice)) + if(isnull(choice) || !user.is_holding(src)) return for(var/datum/action/thing as anything in selectable_actions) @@ -105,7 +105,7 @@ names += initial(thing.name) var/choice = tgui_input_list(user, message = "Select an ability", title = "Bitrunning Program", items = names) - if(isnull(choice)) + if(isnull(choice) || !user.is_holding(src)) return for(var/obj/thing as anything in selectable_items) diff --git a/code/modules/bitrunning/objects/netpod.dm b/code/modules/bitrunning/objects/netpod.dm index 5c8e399292f..a1a681cab05 100644 --- a/code/modules/bitrunning/objects/netpod.dm +++ b/code/modules/bitrunning/objects/netpod.dm @@ -24,12 +24,7 @@ /// Static list of outfits to select from var/list/cached_outfits = list() -/obj/machinery/netpod/Initialize(mapload) - . = ..() - - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/netpod/LateInitialize() +/obj/machinery/netpod/post_machine_initialize() . = ..() disconnect_damage = BASE_DISCONNECT_DAMAGE diff --git a/code/modules/bitrunning/objects/quantum_console.dm b/code/modules/bitrunning/objects/quantum_console.dm index 9dc829c48cd..9a0f48ae80b 100644 --- a/code/modules/bitrunning/objects/quantum_console.dm +++ b/code/modules/bitrunning/objects/quantum_console.dm @@ -12,11 +12,8 @@ . = ..() desc = "Even in the distant year [CURRENT_STATION_YEAR], Nanostrasen is still using REST APIs. How grim." - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/computer/quantum_console/LateInitialize() +/obj/machinery/computer/quantum_console/post_machine_initialize() . = ..() - find_server() /obj/machinery/computer/quantum_console/ui_interact(mob/user, datum/tgui/ui) diff --git a/code/modules/bitrunning/server/_parent.dm b/code/modules/bitrunning/server/_parent.dm index b9d8808607e..06b49d790a5 100644 --- a/code/modules/bitrunning/server/_parent.dm +++ b/code/modules/bitrunning/server/_parent.dm @@ -49,12 +49,7 @@ /// Cooldown between being able to toggle broadcasting COOLDOWN_DECLARE(broadcast_toggle_cd) -/obj/machinery/quantum_server/Initialize(mapload) - . = ..() - - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/quantum_server/LateInitialize() +/obj/machinery/quantum_server/post_machine_initialize() . = ..() radio = new(src) diff --git a/code/modules/capture_the_flag/ctf_game.dm b/code/modules/capture_the_flag/ctf_game.dm index e3b9fb37869..38a7318b554 100644 --- a/code/modules/capture_the_flag/ctf_game.dm +++ b/code/modules/capture_the_flag/ctf_game.dm @@ -221,7 +221,6 @@ return INITIALIZE_HINT_LATELOAD /obj/item/ctf_flag/LateInitialize() - . = ..() ctf_game = GLOB.ctf_games[game_id] //Flags don't create ctf games by themselves since you can get ctf flags from christmas trees. /obj/item/ctf_flag/Destroy() @@ -464,7 +463,12 @@ /obj/structure/table/reinforced/ctf resistance_flags = INDESTRUCTIBLE - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION + +/obj/structure/table/reinforced/ctf/wrench_act_secondary(mob/living/user, obj/item/tool) + return NONE + +/obj/structure/table/reinforced/ctf/screwdriver_act_secondary(mob/living/user, obj/item/tool) + return NONE #define CTF_LOADING_UNLOADED 0 #define CTF_LOADING_LOADING 1 diff --git a/code/modules/capture_the_flag/medieval_sim/medisim_game.dm b/code/modules/capture_the_flag/medieval_sim/medisim_game.dm index 3546ce0881d..18e1cd13e7e 100644 --- a/code/modules/capture_the_flag/medieval_sim/medisim_game.dm +++ b/code/modules/capture_the_flag/medieval_sim/medisim_game.dm @@ -12,9 +12,8 @@ /obj/machinery/ctf/spawner/medisim/Initialize(mapload) . = ..() ctf_game.setup_rules(victory_rejoin_text = "Teams have been cleared. The next game is starting automatically. Rejoin a team if you wish!", auto_restart = TRUE) - return INITIALIZE_HINT_LATELOAD //Start CTF needs to run after both medisim spawners have initalized. -/obj/machinery/ctf/spawner/medisim/LateInitialize() +/obj/machinery/ctf/spawner/medisim/post_machine_initialize() . = ..() ctf_game.start_ctf() diff --git a/code/modules/cards/deck/deck.dm b/code/modules/cards/deck/deck.dm index 47f45eeb5ab..54f8a5feba6 100644 --- a/code/modules/cards/deck/deck.dm +++ b/code/modules/cards/deck/deck.dm @@ -11,6 +11,7 @@ hitsound = null attack_verb_continuous = list("attacks") attack_verb_simple = list("attack") + interaction_flags_click = NEED_DEXTERITY|FORBID_TELEKINESIS_REACH /// The amount of time it takes to shuffle var/shuffle_time = DECK_SHUFFLE_TIME /// Deck shuffling cooldown. @@ -145,13 +146,13 @@ attack_hand(user, modifiers, flip_card = TRUE) return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN -/obj/item/toy/cards/deck/AltClick(mob/living/user) - if(user.can_perform_action(src, NEED_DEXTERITY|FORBID_TELEKINESIS_REACH)) - if(HAS_TRAIT(src, TRAIT_WIELDED)) - shuffle_cards(user) - else - to_chat(user, span_notice("You must hold the [src] with both hands to shuffle.")) - return ..() +/obj/item/toy/cards/deck/click_alt(mob/living/user) + if(!HAS_TRAIT(src, TRAIT_WIELDED)) + to_chat(user, span_notice("You must hold the [src] with both hands to shuffle.")) + return CLICK_ACTION_BLOCKING + + shuffle_cards(user) + return CLICK_ACTION_SUCCESS /obj/item/toy/cards/deck/update_icon_state() switch(count_cards()) diff --git a/code/modules/cards/singlecard.dm b/code/modules/cards/singlecard.dm index 169715c51d9..e03c5800346 100644 --- a/code/modules/cards/singlecard.dm +++ b/code/modules/cards/singlecard.dm @@ -14,6 +14,7 @@ throw_range = 7 attack_verb_continuous = list("attacks") attack_verb_simple = list("attack") + interaction_flags_click = NEED_DEXTERITY|FORBID_TELEKINESIS_REACH /// Artistic style of the deck var/deckstyle = "nanotrasen" /// If the cards in the deck have different icon states (blank and CAS decks do not) @@ -237,8 +238,7 @@ if(isturf(src.loc)) // only display tihs message when flipping in a visible spot like on a table user.balloon_alert_to_viewers("flips a card") -/obj/item/toy/singlecard/AltClick(mob/living/carbon/human/user) - if(user.can_perform_action(src, NEED_DEXTERITY|FORBID_TELEKINESIS_REACH)) - transform = turn(transform, 90) +/obj/item/toy/singlecard/click_alt(mob/living/carbon/human/user) + transform = turn(transform, 90) // use the simple_rotation component to make this turn with Alt+RMB & Alt+LMB at some point in the future - TimT - return ..() + return CLICK_ACTION_SUCCESS diff --git a/code/modules/cargo/bounties/assistant.dm b/code/modules/cargo/bounties/assistant.dm index 7d345802eef..636b4f4791b 100644 --- a/code/modules/cargo/bounties/assistant.dm +++ b/code/modules/cargo/bounties/assistant.dm @@ -257,7 +257,7 @@ ..() fluid_type = pick(AQUARIUM_FLUID_FRESHWATER, AQUARIUM_FLUID_SALTWATER, AQUARIUM_FLUID_SULPHWATEVER) name = "[fluid_type] Fish" - description = "We need [lowertext(fluid_type)] fish to populate our aquariums with. Fishes that are dead or bought from cargo will only be paid half as much." + description = "We need [LOWER_TEXT(fluid_type)] fish to populate our aquariums with. Fishes that are dead or bought from cargo will only be paid half as much." /datum/bounty/item/assistant/fish/fluid/can_ship_fish(obj/item/fish/fishie) return compatible_fluid_type(fishie.required_fluid_type, fluid_type) diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm index 218aed8c681..cf4a5dfc875 100644 --- a/code/modules/cargo/centcom_podlauncher.dm +++ b/code/modules/cargo/centcom_podlauncher.dm @@ -16,11 +16,8 @@ //The user can change properties of the supplypod using the UI, and change the way that items are taken from the bay (One at a time, ordered, random, etc) //Many of the effects of the supplypod set here are put into action in supplypod.dm -/client/proc/centcom_podlauncher() //Creates a verb for admins to open up the ui - set name = "Config/Launch Supplypod" - set desc = "Configure and launch a CentCom supplypod full of whatever your heart desires!" - set category = "Admin.Events" - new /datum/centcom_podlauncher(usr)//create the datum +ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure and launch a CentCom supplypod full of whatever your heart desires!", ADMIN_CATEGORY_EVENTS) + new /datum/centcom_podlauncher(user.mob) //Variables declared to change how items in the launch bay are picked and launched. (Almost) all of these are changed in the ui_act proc //Some effect groups are choices, while other are booleans. This is because some effects can stack, while others dont (ex: you can stack explosion and quiet, but you cant stack ordered launch and random launch) diff --git a/code/modules/cargo/packs/costumes_toys.dm b/code/modules/cargo/packs/costumes_toys.dm index e23e6112a4b..de84a263597 100644 --- a/code/modules/cargo/packs/costumes_toys.dm +++ b/code/modules/cargo/packs/costumes_toys.dm @@ -268,3 +268,15 @@ crate_name = "corgi pinata kit" crate_type = /obj/structure/closet/crate/wooden discountable = SUPPLY_PACK_STD_DISCOUNTABLE + +/datum/supply_pack/costumes_toys/balloons + name = "Long Balloons Kit" + desc = "This crate contains a box of long balloons, plus a skillchip for non-clowns to join the fun! Extra layer of safety so clowns at CentCom won't get to them." + cost = CARGO_CRATE_VALUE * 4 + contains = list( + /obj/item/storage/box/balloons, + /obj/item/skillchip/job/clown, + ) + crate_name = "long balloons kit" + crate_type = /obj/structure/closet/crate/wooden + discountable = SUPPLY_PACK_STD_DISCOUNTABLE diff --git a/code/modules/cargo/supplypod_beacon.dm b/code/modules/cargo/supplypod_beacon.dm index 999e7d76eec..8f1166002de 100644 --- a/code/modules/cargo/supplypod_beacon.dm +++ b/code/modules/cargo/supplypod_beacon.dm @@ -9,9 +9,14 @@ w_class = WEIGHT_CLASS_SMALL armor_type = /datum/armor/supplypod_beacon resistance_flags = FIRE_PROOF + interaction_flags_click = ALLOW_SILICON_REACH + /// The linked console var/obj/machinery/computer/cargo/express/express_console + /// If linked var/linked = FALSE + /// If this is ready to launch var/ready = FALSE + /// If it's been launched var/launched = FALSE /datum/armor/supplypod_beacon @@ -90,13 +95,12 @@ update_status(SP_READY) to_chat(user, span_notice("[src] linked to [C].")) -/obj/item/supplypod_beacon/AltClick(mob/user) - if (!user.can_perform_action(src, ALLOW_SILICON_REACH)) - return - if (express_console) - unlink_console() - else +/obj/item/supplypod_beacon/click_alt(mob/user) + if(!express_console) to_chat(user, span_alert("There is no linked console.")) + return CLICK_ACTION_BLOCKING + unlink_console() + return CLICK_ACTION_SUCCESS /obj/item/supplypod_beacon/attackby(obj/item/W, mob/user) if(!istype(W, /obj/item/pen)) //give a tag that is visible from the linked express console diff --git a/code/modules/cargo/universal_scanner.dm b/code/modules/cargo/universal_scanner.dm index 68fe533959a..80a821a1f5e 100644 --- a/code/modules/cargo/universal_scanner.dm +++ b/code/modules/cargo/universal_scanner.dm @@ -129,15 +129,15 @@ payments_acc = null to_chat(user, span_notice("You clear the registered account.")) -/obj/item/universal_scanner/AltClick(mob/user) - . = ..() +/obj/item/universal_scanner/click_alt(mob/user) if(!scanning_mode == SCAN_SALES_TAG) - return + return CLICK_ACTION_BLOCKING var/potential_cut = input("How much would you like to pay out to the registered card?","Percentage Profit ([round(cut_min*100)]% - [round(cut_max*100)]%)") as num|null if(!potential_cut) cut_multiplier = initial(cut_multiplier) cut_multiplier = clamp(round(potential_cut/100, cut_min), cut_min, cut_max) to_chat(user, span_notice("[round(cut_multiplier*100)]% profit will be received if a package with a barcode is sold.")) + return CLICK_ACTION_SUCCESS /obj/item/universal_scanner/examine(mob/user) . = ..() diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 45ccda8b92b..3272620a865 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -194,8 +194,6 @@ var/list/spell_tabs = list() ///A lazy list of atoms we've examined in the last RECENT_EXAMINE_MAX_WINDOW (default 2) seconds, so that we will call [/atom/proc/examine_more] instead of [/atom/proc/examine] on them when examining var/list/recent_examines - ///Our object window datum. It stores info about and handles behavior for the object tab - var/datum/object_window_info/obj_window var/list/parallax_layers var/list/parallax_layers_cached @@ -266,3 +264,6 @@ /// Does this client have typing indicators enabled? var/typing_indicators = FALSE + + /// Loot panel for the client + var/datum/lootpanel/loot_panel diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 9523d4d52c6..b25d7c2e5ae 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -38,7 +38,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( //SKYRAT EDIT ADDITION END #ifndef TESTING - if (lowertext(hsrc_command) == "_debug") //disable the integrated byond vv in the client side debugging tools since it doesn't respect vv read protections + if (LOWER_TEXT(hsrc_command) == "_debug") //disable the integrated byond vv in the client side debugging tools since it doesn't respect vv read protections return #endif @@ -157,6 +157,15 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( to_chat(src, "Become a BYOND member to access member-perks and features, as well as support the engine that makes this game possible. Only 10 bucks for 3 months! Click Here to find out more.") return FALSE return TRUE + +/client/proc/is_localhost() + var/static/localhost_addresses = list( + "127.0.0.1", + "::1", + null, + ) + return address in localhost_addresses + /* * Call back proc that should be checked in all paths where a client can send messages * @@ -254,32 +263,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( GLOB.ahelp_tickets.ClientLogin(src) GLOB.interviews.client_login(src) GLOB.requests.client_login(src) - var/connecting_admin = FALSE //because de-admined admins connecting should be treated like admins. - //Admin Authorisation - var/datum/admins/admin_datum = GLOB.admin_datums[ckey] - if (!isnull(admin_datum)) - admin_datum.associate(src) - connecting_admin = TRUE - else if(GLOB.deadmins[ckey]) - add_verb(src, /client/proc/readmin) - connecting_admin = TRUE - //SKYRAT EDIT ADDITION //We will check the population here, because we need to know if the client is an admin or not. - if(!check_population(connecting_admin)) - qdel(src) - return - // SKYRAT EDIT END - if(CONFIG_GET(flag/autoadmin)) - if(!GLOB.admin_datums[ckey]) - var/list/autoadmin_ranks = ranks_from_rank_name(CONFIG_GET(string/autoadmin_rank)) - if (autoadmin_ranks.len == 0) - to_chat(world, "Autoadmin rank not found") - else - new /datum/admins(autoadmin_ranks, ckey) - if(CONFIG_GET(flag/enable_localhost_rank) && !connecting_admin) - var/localhost_addresses = list("127.0.0.1", "::1") - if(isnull(address) || (address in localhost_addresses)) - var/datum/admin_rank/localhost_rank = new("!localhost!", R_EVERYTHING, R_DBRANKS, R_EVERYTHING) //+EVERYTHING -DBRANKS *EVERYTHING - new /datum/admins(list(localhost_rank), ckey, 1, 1) //preferences datum - also holds some persistent data for the client (because we may as well keep these datums to a minimum) prefs = GLOB.preferences_datums[ckey] if(prefs) @@ -352,6 +335,34 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( . = ..() //calls mob.Login() + + // Admin Verbs need the client's mob to exist. Must be after ..() + var/connecting_admin = FALSE //because de-admined admins connecting should be treated like admins. + //Admin Authorisation + var/datum/admins/admin_datum = GLOB.admin_datums[ckey] + if (!isnull(admin_datum)) + admin_datum.associate(src) + connecting_admin = TRUE + else if(GLOB.deadmins[ckey]) + add_verb(src, /client/proc/readmin) + connecting_admin = TRUE + //SKYRAT EDIT ADDITION //We will check the population here, because we need to know if the client is an admin or not. + if(!check_population(connecting_admin)) + qdel(src) + return + // SKYRAT EDIT END + if(CONFIG_GET(flag/autoadmin)) + if(!GLOB.admin_datums[ckey]) + var/list/autoadmin_ranks = ranks_from_rank_name(CONFIG_GET(string/autoadmin_rank)) + if (autoadmin_ranks.len == 0) + to_chat(world, "Autoadmin rank not found") + else + new /datum/admins(autoadmin_ranks, ckey) + + if(CONFIG_GET(flag/enable_localhost_rank) && !connecting_admin && is_localhost()) + var/datum/admin_rank/localhost_rank = new("!localhost!", R_EVERYTHING, R_DBRANKS, R_EVERYTHING) //+EVERYTHING -DBRANKS *EVERYTHING + new /datum/admins(list(localhost_rank), ckey, 1, 1) + if (length(GLOB.stickybanadminexemptions)) GLOB.stickybanadminexemptions -= ckey if (!length(GLOB.stickybanadminexemptions)) @@ -538,6 +549,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( if (!interviewee) initialize_menus() + loot_panel = new(src) + view_size = new(src, getScreenSize(prefs.read_preference(/datum/preference/toggle/widescreen))) view_size.resetFormat() view_size.setZoomMode() @@ -578,8 +591,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( SSserver_maint.UpdateHubStatus() if(credits) QDEL_LIST(credits) - if(obj_window) - QDEL_NULL(obj_window) if(holder) adminGreet(1) holder.owner = null @@ -610,6 +621,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( QDEL_NULL(void) QDEL_NULL(tooltips) QDEL_NULL(open_loadout_ui) //SKYRAT EDIT ADDITION + QDEL_NULL(loot_panel) seen_messages = null Master.UpdateTickRate() ..() //Even though we're going to be hard deleted there are still some things that want to know the destroy is happening @@ -1201,7 +1213,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( return 0 if(!isnum(player_age) || player_age < 0) - return 0 + return 0 if(!isnum(days_needed)) return 0 @@ -1211,13 +1223,10 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( /// Attempts to make the client orbit the given object, for administrative purposes. /// If they are not an observer, will try to aghost them. /client/proc/admin_follow(atom/movable/target) - var/can_ghost = TRUE - - if (!isobserver(mob)) - can_ghost = admin_ghost() - - if(!can_ghost) - return FALSE + if(!isobserver(mob)) + SSadmin_verbs.dynamic_invoke_verb(src, /datum/admin_verb/admin_ghost) + if(!isobserver(mob)) + return var/mob/dead/observer/observer = mob observer.ManualFollow(target) diff --git a/code/modules/client/preferences/glasses.dm b/code/modules/client/preferences/glasses.dm index 03c975abce7..a08f15955ea 100644 --- a/code/modules/client/preferences/glasses.dm +++ b/code/modules/client/preferences/glasses.dm @@ -11,7 +11,7 @@ if (value == "Random") return icon('icons/effects/random_spawners.dmi', "questionmark") else - return icon('icons/obj/clothing/glasses.dmi', "glasses_[lowertext(value)]") + return icon('icons/obj/clothing/glasses.dmi', "glasses_[LOWER_TEXT(value)]") /datum/preference/choiced/glasses/is_accessible(datum/preferences/preferences) if (!..(preferences)) diff --git a/code/modules/client/preferences/middleware/antags.dm b/code/modules/client/preferences/middleware/antags.dm index b3bc613d2ee..abd9495d09a 100644 --- a/code/modules/client/preferences/middleware/antags.dm +++ b/code/modules/client/preferences/middleware/antags.dm @@ -180,4 +180,4 @@ GLOBAL_LIST_INIT(non_ruleset_antagonists, list( /// Serializes an antag name to be used for preferences UI /proc/serialize_antag_name(antag_name) // These are sent through CSS, so they need to be safe to use as class names. - return lowertext(sanitize_css_class_name(antag_name)) + return LOWER_TEXT(sanitize_css_class_name(antag_name)) diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm index dc55b72b09d..4ca59bf0f3e 100644 --- a/code/modules/client/verbs/ooc.dm +++ b/code/modules/client/verbs/ooc.dm @@ -144,33 +144,28 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8") set category = "Server" if(IsAdminAdvancedProcCall()) return - var/newColor = input(src, "Please select the new player OOC color.", "OOC color") as color|null + +ADMIN_VERB(set_ooc_color, R_FUN, "Set Player OOC Color", "Modifies the global OOC color.", ADMIN_CATEGORY_SERVER) + var/newColor = input(user, "Please select the new player OOC color.", "OOC color") as color|null if(isnull(newColor)) return - if(!check_rights(R_FUN)) - message_admins("[usr.key] has attempted to use the Set Player OOC Color verb!") - log_admin("[key_name(usr)] tried to set player ooc color without authorization.") - return var/new_color = sanitize_color(newColor) - message_admins("[key_name_admin(usr)] has set the players' ooc color to [new_color].") - log_admin("[key_name_admin(usr)] has set the player ooc color to [new_color].") + message_admins("[key_name_admin(user)] has set the players' ooc color to [new_color].") + log_admin("[key_name_admin(user)] has set the player ooc color to [new_color].") GLOB.OOC_COLOR = new_color - /client/proc/reset_ooc() set name = "Reset Player OOC Color" set desc = "Returns player OOC Color to default" set category = "Server" if(IsAdminAdvancedProcCall()) return - if(tgui_alert(usr, "Are you sure you want to reset the OOC color of all players?", "Reset Player OOC Color", list("Yes", "No")) != "Yes") + +ADMIN_VERB(reset_ooc_color, R_FUN, "Reset Player OOC Color", "Returns player OOC color to default.", ADMIN_CATEGORY_SERVER) + if(tgui_alert(user, "Are you sure you want to reset the OOC color of all players?", "Reset Player OOC Color", list("Yes", "No")) != "Yes") return - if(!check_rights(R_FUN)) - message_admins("[usr.key] has attempted to use the Reset Player OOC Color verb!") - log_admin("[key_name(usr)] tried to reset player ooc color without authorization.") - return - message_admins("[key_name_admin(usr)] has reset the players' ooc color.") - log_admin("[key_name_admin(usr)] has reset player ooc color.") + message_admins("[key_name_admin(user)] has reset the players' ooc color.") + log_admin("[key_name_admin(user)] has reset player ooc color.") GLOB.OOC_COLOR = null //Checks admin notice diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index 81e87e84baa..c44d5be4ef8 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -65,23 +65,19 @@ H.set_eye_blur_if_lower(10 SECONDS) eyes.apply_organ_damage(5) -/obj/item/clothing/glasses/AltClick(mob/user) - . = ..() //SKYRAT EDIT ADDITION - if(glass_colour_type && !forced_glass_color && ishuman(user)) - var/mob/living/carbon/human/human_user = user +/obj/item/clothing/glasses/click_alt(mob/user) + if(isnull(glass_colour_type) || forced_glass_color || !ishuman(user)) + return NONE + var/mob/living/carbon/human/human_user = user - if (human_user.glasses != src) - return ..() - - if (HAS_TRAIT_FROM(human_user, TRAIT_SEE_GLASS_COLORS, GLASSES_TRAIT)) - REMOVE_TRAIT(human_user, TRAIT_SEE_GLASS_COLORS, GLASSES_TRAIT) - to_chat(human_user, span_notice("You will no longer see glasses colors.")) - else - ADD_TRAIT(human_user, TRAIT_SEE_GLASS_COLORS, GLASSES_TRAIT) - to_chat(human_user, span_notice("You will now see glasses colors.")) - human_user.update_glasses_color(src, TRUE) + if (HAS_TRAIT_FROM(human_user, TRAIT_SEE_GLASS_COLORS, GLASSES_TRAIT)) + REMOVE_TRAIT(human_user, TRAIT_SEE_GLASS_COLORS, GLASSES_TRAIT) + to_chat(human_user, span_notice("You will no longer see glasses colors.")) else - return ..() + ADD_TRAIT(human_user, TRAIT_SEE_GLASS_COLORS, GLASSES_TRAIT) + to_chat(human_user, span_notice("You will now see glasses colors.")) + human_user.update_glasses_color(src, TRUE) + return CLICK_ACTION_SUCCESS /obj/item/clothing/glasses/proc/change_glass_color(mob/living/carbon/human/H, datum/client_colour/glass_colour/new_color_type) var/old_colour_type = glass_colour_type @@ -664,18 +660,19 @@ var/datum/atom_hud/our_hud = GLOB.huds[hud] our_hud.hide_from(user) -/obj/item/clothing/glasses/debug/AltClick(mob/user) - . = ..() - if(ishuman(user)) - if(xray) - vision_flags &= ~SEE_MOBS|SEE_OBJS - REMOVE_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT) - else - vision_flags |= SEE_MOBS|SEE_OBJS - ADD_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT) - xray = !xray - var/mob/living/carbon/human/human_user = user - human_user.update_sight() +/obj/item/clothing/glasses/debug/click_alt(mob/user) + if(!ishuman(user)) + return CLICK_ACTION_BLOCKING + if(xray) + vision_flags &= ~SEE_MOBS|SEE_OBJS + REMOVE_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT) + else + vision_flags |= SEE_MOBS|SEE_OBJS + ADD_TRAIT(user, TRAIT_XRAY_VISION, GLASSES_TRAIT) + xray = !xray + var/mob/living/carbon/human/human_user = user + human_user.update_sight() + return CLICK_ACTION_SUCCESS /obj/item/clothing/glasses/regular/kim name = "binoclard lenses" diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm index 0c48cb102b2..5f63e0c3464 100644 --- a/code/modules/clothing/gloves/_gloves.dm +++ b/code/modules/clothing/gloves/_gloves.dm @@ -16,6 +16,8 @@ attack_verb_simple = list("challenge") strip_delay = 20 equip_delay_other = 40 + article = "a pair of" + // Path variable. If defined, will produced the type through interaction with wirecutters. var/cut_type = null /// Used for handling bloody gloves leaving behind bloodstains on objects. Will be decremented whenever a bloodstain is left behind, and be incremented when the gloves become bloody. diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 7741251f3f5..236d94c39fa 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -195,6 +195,21 @@ acid = 80 wound = 15 +/obj/item/clothing/head/helmet/balloon + name = "balloon helmet" + desc = "A helmet made out of balloons. Its likes saw great usage in the Great Clown - Mime War. Surprisingly resistant to fire. Mimes were doing unspeakable things." + icon_state = "helmet_balloon" + inhand_icon_state = "helmet_balloon" + armor_type = /datum/armor/balloon + flags_inv = HIDEHAIR|HIDEEARS|HIDESNOUT + resistance_flags = FIRE_PROOF + dog_fashion = null + +/datum/armor/balloon + melee = 10 + fire = 60 + acid = 50 + /obj/item/clothing/head/helmet/toggleable/justice name = "helmet of justice" desc = "WEEEEOOO. WEEEEEOOO. WEEEEOOOO." @@ -423,16 +438,6 @@ armor_type = /datum/armor/knight_greyscale material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS //Can change color and add prefix -/datum/armor/knight_greyscale - melee = 35 - bullet = 10 - laser = 10 - energy = 10 - bomb = 10 - bio = 10 - fire = 40 - acid = 40 - /obj/item/clothing/head/helmet/skull name = "skull helmet" desc = "An intimidating tribal helmet, it doesn't look very comfortable." diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index 779559b4fe4..c212481453b 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -173,6 +173,8 @@ armor_type = /datum/armor/fedora_det_hat icon_state = "detective" inhand_icon_state = "det_hat" + interaction_flags_click = NEED_DEXTERITY|NEED_HANDS + /// Cooldown for retrieving precious candy corn on alt click var/candy_cooldown = 0 dog_fashion = /datum/dog_fashion/head/detective ///Path for the flask that spawns inside their hat roundstart @@ -198,17 +200,16 @@ . = ..() . += span_notice("Alt-click to take a candy corn.") -/obj/item/clothing/head/fedora/det_hat/AltClick(mob/user) - . = ..() - if(loc != user || !user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS)) - return - if(candy_cooldown < world.time) - var/obj/item/food/candy_corn/CC = new /obj/item/food/candy_corn(src) - user.put_in_hands(CC) - to_chat(user, span_notice("You slip a candy corn from your hat.")) - candy_cooldown = world.time+1200 - else +/obj/item/clothing/head/fedora/det_hat/click_alt(mob/user) + if(candy_cooldown >= world.time) to_chat(user, span_warning("You just took a candy corn! You should wait a couple minutes, lest you burn through your stash.")) + return CLICK_ACTION_BLOCKING + + var/obj/item/food/candy_corn/CC = new /obj/item/food/candy_corn(src) + user.put_in_hands(CC) + to_chat(user, span_notice("You slip a candy corn from your hat.")) + candy_cooldown = world.time+1200 + return CLICK_ACTION_SUCCESS /obj/item/clothing/head/fedora/det_hat/minor flask_path = /obj/item/reagent_containers/cup/glass/flask/det/minor @@ -221,6 +222,7 @@ icon_state = "detective" inhand_icon_state = "det_hat" dog_fashion = /datum/dog_fashion/head/detective + interaction_flags_click = FORBID_TELEKINESIS_REACH ///prefix our phrases must begin with var/prefix = "go go gadget" ///an assoc list of phrase = item (like gun = revolver) @@ -277,7 +279,7 @@ return var/input = tgui_input_text(user, "What is the activation phrase?", "Activation phrase", "gadget", max_length = 26) - if(!input) + if(!input || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) return if(input in items_by_phrase) balloon_alert(user, "already used!") @@ -293,16 +295,16 @@ /obj/item/clothing/head/fedora/inspector_hat/attack_self(mob/user) . = ..() var/phrase = tgui_input_list(user, "What item do you want to remove by phrase?", "Item Removal", items_by_phrase) - if(!phrase) + if(!phrase || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) return user.put_in_inactive_hand(items_by_phrase[phrase]) -/obj/item/clothing/head/fedora/inspector_hat/AltClick(mob/user) - . = ..() +/obj/item/clothing/head/fedora/inspector_hat/click_alt(mob/user) var/new_prefix = tgui_input_text(user, "What should be the new prefix?", "Activation prefix", prefix, max_length = 24) - if(!new_prefix) - return + if(!new_prefix || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) + return CLICK_ACTION_BLOCKING prefix = new_prefix + return CLICK_ACTION_SUCCESS /obj/item/clothing/head/fedora/inspector_hat/Exited(atom/movable/gone, direction) . = ..() diff --git a/code/modules/clothing/head/soft_caps.dm b/code/modules/clothing/head/soft_caps.dm index 0b0a6fb4d50..92517d4a7dd 100644 --- a/code/modules/clothing/head/soft_caps.dm +++ b/code/modules/clothing/head/soft_caps.dm @@ -5,11 +5,14 @@ worn_icon = 'icons/mob/clothing/head/hats.dmi' icon_state = "cargosoft" inhand_icon_state = "greyscale_softcap" //todo wip + interaction_flags_click = NEED_DEXTERITY + /// For setting icon archetype var/soft_type = "cargo" + /// If there is a suffix to append var/soft_suffix = "soft" dog_fashion = /datum/dog_fashion/head/cargo_tech - + /// Whether this is on backwards... Woah, cool var/flipped = FALSE /obj/item/clothing/head/soft/dropped() @@ -24,10 +27,9 @@ flip(usr) -/obj/item/clothing/head/soft/AltClick(mob/user) - ..() - if(user.can_perform_action(src, NEED_DEXTERITY)) - flip(user) +/obj/item/clothing/head/soft/click_alt(mob/user) + flip(user) + return CLICK_ACTION_SUCCESS /obj/item/clothing/head/soft/proc/flip(mob/user) diff --git a/code/modules/clothing/head/tophat.dm b/code/modules/clothing/head/tophat.dm index 26087ab6232..2affc4c63da 100644 --- a/code/modules/clothing/head/tophat.dm +++ b/code/modules/clothing/head/tophat.dm @@ -36,4 +36,13 @@ var/mob/living/basic/rabbit/bunbun = new(get_turf(magician)) bunbun.mob_try_pickup(magician, instant=TRUE) +/obj/item/clothing/head/hats/tophat/balloon + name = "balloon top-hat" + desc = "It's an colourful looking top-hat to match yout colourful personality." + icon_state = "balloon_tophat" + inhand_icon_state = "balloon_that" + throwforce = 0 + resistance_flags = FIRE_PROOF + dog_fashion = null + #undef RABBIT_CD_TIME diff --git a/code/modules/clothing/masks/animal_masks.dm b/code/modules/clothing/masks/animal_masks.dm index c2013b99177..5df5c6738d8 100644 --- a/code/modules/clothing/masks/animal_masks.dm +++ b/code/modules/clothing/masks/animal_masks.dm @@ -46,11 +46,12 @@ GLOBAL_LIST_INIT(cursed_animal_masks, list( if(clothing_flags & VOICEBOX_TOGGLABLE) . += span_notice("Its voicebox is currently [clothing_flags & VOICEBOX_DISABLED ? "disabled" : "enabled"]. Alt-click to toggle it.") -/obj/item/clothing/mask/animal/AltClick(mob/user) - . = ..() - if(clothing_flags & VOICEBOX_TOGGLABLE) - clothing_flags ^= VOICEBOX_DISABLED - to_chat(user, span_notice("You [clothing_flags & VOICEBOX_DISABLED ? "disabled" : "enabled"] [src]'s voicebox.")) +/obj/item/clothing/mask/animal/click_alt(mob/user) + if(!(clothing_flags & VOICEBOX_TOGGLABLE)) + return NONE + clothing_flags ^= VOICEBOX_DISABLED + to_chat(user, span_notice("You [clothing_flags & VOICEBOX_DISABLED ? "disabled" : "enabled"] [src]'s voicebox.")) + return CLICK_ACTION_SUCCESS /obj/item/clothing/mask/animal/proc/make_cursed() //apply cursed effects. ADD_TRAIT(src, TRAIT_NODROP, CURSED_MASK_TRAIT) diff --git a/code/modules/clothing/masks/bandana.dm b/code/modules/clothing/masks/bandana.dm index 4a97384fa39..cd4b3980e55 100644 --- a/code/modules/clothing/masks/bandana.dm +++ b/code/modules/clothing/masks/bandana.dm @@ -53,34 +53,36 @@ worn_icon_state = initial(worn_icon_state) undyeable = initial(undyeable) -/obj/item/clothing/mask/bandana/AltClick(mob/user) - . = ..() - if(iscarbon(user)) - var/mob/living/carbon/char = user - var/matrix/widen = matrix() - if((char.get_item_by_slot(ITEM_SLOT_NECK) == src) || (char.get_item_by_slot(ITEM_SLOT_MASK) == src) || (char.get_item_by_slot(ITEM_SLOT_HEAD) == src)) - to_chat(user, span_warning("You can't tie [src] while wearing it!")) - return - else if(slot_flags & ITEM_SLOT_HEAD) - to_chat(user, span_warning("You must undo [src] before you can tie it into a neckerchief!")) - return - else if(!user.is_holding(src)) - to_chat(user, span_warning("You must be holding [src] in order to tie it!")) - return +/obj/item/clothing/mask/bandana/click_alt(mob/user) + if(!iscarbon(user)) + return NONE - if(slot_flags & ITEM_SLOT_MASK) - undyeable = TRUE - slot_flags = ITEM_SLOT_NECK - worn_y_offset = -3 - widen.Scale(1.25, 1) - transform = widen - user.visible_message(span_notice("[user] ties [src] up like a neckerchief."), span_notice("You tie [src] up like a neckerchief.")) - else - undyeable = initial(undyeable) - slot_flags = initial(slot_flags) - worn_y_offset = initial(worn_y_offset) - transform = initial(transform) - user.visible_message(span_notice("[user] unties the neckercheif."), span_notice("You untie the neckercheif.")) + var/mob/living/carbon/char = user + var/matrix/widen = matrix() + if((char.get_item_by_slot(ITEM_SLOT_NECK) == src) || (char.get_item_by_slot(ITEM_SLOT_MASK) == src) || (char.get_item_by_slot(ITEM_SLOT_HEAD) == src)) + to_chat(user, span_warning("You can't tie [src] while wearing it!")) + return CLICK_ACTION_BLOCKING + else if(slot_flags & ITEM_SLOT_HEAD) + to_chat(user, span_warning("You must undo [src] before you can tie it into a neckerchief!")) + return CLICK_ACTION_BLOCKING + else if(!user.is_holding(src)) + to_chat(user, span_warning("You must be holding [src] in order to tie it!")) + return CLICK_ACTION_BLOCKING + + if(slot_flags & ITEM_SLOT_MASK) + undyeable = TRUE + slot_flags = ITEM_SLOT_NECK + worn_y_offset = -3 + widen.Scale(1.25, 1) + transform = widen + user.visible_message(span_notice("[user] ties [src] up like a neckerchief."), span_notice("You tie [src] up like a neckerchief.")) + else + undyeable = initial(undyeable) + slot_flags = initial(slot_flags) + worn_y_offset = initial(worn_y_offset) + transform = initial(transform) + user.visible_message(span_notice("[user] unties the neckercheif."), span_notice("You untie the neckercheif.")) + return CLICK_ACTION_SUCCESS /obj/item/clothing/mask/bandana/red name = "red bandana" @@ -229,14 +231,16 @@ greyscale_config_inhand_left = /datum/greyscale_config/facescarf/inhands_left greyscale_config_inhand_right = /datum/greyscale_config/facescarf/inhands_right flags_1 = IS_PLAYER_COLORABLE_1 + interaction_flags_click = NEED_DEXTERITY /obj/item/clothing/mask/facescarf/attack_self(mob/user) adjustmask(user) -/obj/item/clothing/mask/facescarf/AltClick(mob/user) - ..() - if(user.can_perform_action(src, NEED_DEXTERITY)) - adjustmask(user) + +/obj/item/clothing/mask/facescarf/click_alt(mob/user) + adjustmask(user) + return CLICK_ACTION_SUCCESS + /obj/item/clothing/mask/facescarf/examine(mob/user) . = ..() diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm index 8ba15fe521d..0249f0b1321 100644 --- a/code/modules/clothing/masks/breath.dm +++ b/code/modules/clothing/masks/breath.dm @@ -12,6 +12,7 @@ flags_cover = MASKCOVERSMOUTH visor_flags_cover = MASKCOVERSMOUTH resistance_flags = NONE + interaction_flags_click = NEED_DEXTERITY /datum/armor/mask_breath bio = 50 @@ -23,10 +24,9 @@ /obj/item/clothing/mask/breath/attack_self(mob/user) adjustmask(user) -/obj/item/clothing/mask/breath/AltClick(mob/user) - ..() - if(user.can_perform_action(src, NEED_DEXTERITY)) - adjustmask(user) +/obj/item/clothing/mask/breath/click_alt(mob/user) + adjustmask(user) + return CLICK_ACTION_SUCCESS /obj/item/clothing/mask/breath/examine(mob/user) . = ..() diff --git a/code/modules/clothing/masks/costume.dm b/code/modules/clothing/masks/costume.dm index 893455dcdd0..626d8ce4a65 100644 --- a/code/modules/clothing/masks/costume.dm +++ b/code/modules/clothing/masks/costume.dm @@ -12,14 +12,6 @@ "Pleading" = "pleading" ) -/obj/item/clothing/mask/joy/Initialize(mapload) - . = ..() - register_context() - -/obj/item/clothing/mask/joy/add_context(atom/source, list/context, obj/item/held_item, mob/user) - . = ..() - context[SCREENTIP_CONTEXT_ALT_LMB] = "Change Emotion" - return CONTEXTUAL_SCREENTIP_SET /obj/item/clothing/mask/joy/reskin_obj(mob/user) . = ..() diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index a62f271739b..e07a56155d4 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -73,10 +73,9 @@ else . += span_notice("The tie can be untied with Alt-Click.") -/obj/item/clothing/neck/tie/AltClick(mob/user) - . = ..() +/obj/item/clothing/neck/tie/click_alt(mob/user) if(clip_on) - return + return NONE to_chat(user, span_notice("You concentrate as you begin [is_tied ? "untying" : "tying"] [src]...")) var/tie_timer_actual = tie_timer // Mirrors give you a boost to your tying speed. I realize this stacks and I think that's hilarious. @@ -88,11 +87,11 @@ // Tie/Untie our tie if(!do_after(user, tie_timer_actual)) to_chat(user, span_notice("Your fingers fumble away from [src] as your concentration breaks.")) - return + return CLICK_ACTION_BLOCKING // Clumsy & Dumb people have trouble tying their ties. if((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50)) to_chat(user, span_notice("You just can't seem to get a proper grip on [src]!")) - return + return CLICK_ACTION_BLOCKING // Success! is_tied = !is_tied user.visible_message( @@ -101,6 +100,7 @@ ) update_appearance(UPDATE_ICON) user.update_clothing(ITEM_SLOT_NECK) + return CLICK_ACTION_SUCCESS /obj/item/clothing/neck/tie/update_icon() . = ..() diff --git a/code/modules/clothing/outfits/ert.dm b/code/modules/clothing/outfits/ert.dm index 6d9646b49ee..db20562039b 100644 --- a/code/modules/clothing/outfits/ert.dm +++ b/code/modules/clothing/outfits/ert.dm @@ -388,7 +388,7 @@ ) head = /obj/item/clothing/head/utility/hardhat/welding mask = /obj/item/clothing/mask/gas/atmos - l_hand = /obj/item/areaeditor/blueprints + l_hand = /obj/item/blueprints /datum/outfit/centcom/ert/clown/party name = "ERP Comedian" diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm index 4b0da7092c5..e30dfc2f5ac 100644 --- a/code/modules/clothing/shoes/_shoes.dm +++ b/code/modules/clothing/shoes/_shoes.dm @@ -12,6 +12,8 @@ armor_type = /datum/armor/clothing_shoes slowdown = SHOES_SLOWDOWN strip_delay = 1 SECONDS + article = "a pair of" + var/offset = 0 var/equipped_before_drop = FALSE ///Whether these shoes have laces that can be tied/untied @@ -179,8 +181,7 @@ adjust_laces(SHOES_UNTIED, user) else // if they're someone else's shoes, go knot-wards - var/mob/living/L = user - if(istype(L) && L.body_position == STANDING_UP) + if(istype(living_user) && living_user.body_position == STANDING_UP) to_chat(user, span_warning("You must be on the floor to interact with [src]!")) return if(tied == SHOES_KNOTTED) @@ -194,11 +195,11 @@ to_chat(user, span_notice("You quietly set to work [tied ? "untying" : "knotting"] [loc]'s [src.name]...")) if(HAS_TRAIT(user, TRAIT_CLUMSY)) // based clowns trained their whole lives for this mod_time *= 0.75 - // SKYRAT EDIT START + // SKYRAT EDIT ADDITION START if(HAS_TRAIT(user, TRAIT_STICKY_FINGERS)) // Clowns with thieving gloves will be a menace mod_time *= 0.5 - // SKYRAT EDIT END - if(do_after(user, mod_time, target = our_guy, extra_checks = CALLBACK(src, PROC_REF(still_shoed), our_guy))) + // SKYRAT EDIT ADDITION END + if(do_after(user, mod_time, target = our_guy, extra_checks = CALLBACK(src, PROC_REF(still_shoed), our_guy), hidden = TRUE)) to_chat(user, span_notice("You [tied ? "untie" : "knot"] the laces on [loc]'s [src.name].")) if(tied == SHOES_UNTIED) adjust_laces(SHOES_KNOTTED, user) @@ -208,12 +209,12 @@ user.visible_message(span_danger("[our_guy] stamps on [user]'s hand, mid-shoelace [tied ? "knotting" : "untying"]!"), span_userdanger("Ow! [our_guy] stamps on your hand!"), list(our_guy)) to_chat(our_guy, span_userdanger("You stamp on [user]'s hand! What the- [user.p_they()] [user.p_were()] [tied ? "knotting" : "untying"] your shoelaces!")) user.emote("scream") - if(istype(L)) - var/obj/item/bodypart/ouchie = L.get_bodypart(pick(GLOB.arm_zones)) + if(istype(living_user)) + var/obj/item/bodypart/ouchie = living_user.get_bodypart(pick(GLOB.arm_zones)) if(ouchie) ouchie.receive_damage(brute = 10) - L.adjustStaminaLoss(40) - L.Paralyze(10) + living_user.adjustStaminaLoss(40) + living_user.Paralyze(10) ///checking to make sure we're still on the person we're supposed to be, for lacing do_after's /obj/item/clothing/shoes/proc/still_shoed(mob/living/carbon/our_guy) diff --git a/code/modules/clothing/shoes/gunboots.dm b/code/modules/clothing/shoes/gunboots.dm index d8335b5fcb0..de74703d449 100644 --- a/code/modules/clothing/shoes/gunboots.dm +++ b/code/modules/clothing/shoes/gunboots.dm @@ -59,7 +59,7 @@ shot.original = target shot.fired_from = src shot.firer = wearer // don't hit ourself that would be really annoying - shot.impacted = list(wearer = TRUE) + shot.impacted = list(WEAKREF(wearer) = TRUE) shot.def_zone = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) // they're fired from boots after all shot.preparePixelProjectile(target, wearer) if(!shot.suppressed) diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm index 58cbf7e88e5..785ec9e26f9 100644 --- a/code/modules/clothing/spacesuits/_spacesuits.dm +++ b/code/modules/clothing/spacesuits/_spacesuits.dm @@ -58,11 +58,17 @@ equip_delay_other = 80 resistance_flags = NONE actions_types = list(/datum/action/item_action/toggle_spacesuit) - var/temperature_setting = BODYTEMP_NORMAL /// The default temperature setting - var/obj/item/stock_parts/cell/cell = /obj/item/stock_parts/cell/high /// If this is a path, this gets created as an object in Initialize. - var/cell_cover_open = FALSE /// Status of the cell cover on the suit - var/thermal_on = FALSE /// Status of the thermal regulator - var/show_hud = TRUE /// If this is FALSE the batery status UI will be disabled. This is used for suits that don't use bateries like the changeling's flesh suit mutation. + interaction_flags_click = NEED_DEXTERITY + /// The default temperature setting + var/temperature_setting = BODYTEMP_NORMAL + /// If this is a path, this gets created as an object in Initialize. + var/obj/item/stock_parts/cell/cell = /obj/item/stock_parts/cell/high + /// Status of the cell cover on the suit + var/cell_cover_open = FALSE + /// Status of the thermal regulator + var/thermal_on = FALSE + /// If this is FALSE the batery status UI will be disabled. This is used for suits that don't use bateries like the changeling's flesh suit mutation. + var/show_hud = TRUE /datum/armor/suit_space bio = 100 @@ -190,10 +196,9 @@ return /// Open the cell cover when ALT+Click on the suit -/obj/item/clothing/suit/space/AltClick(mob/living/user) - if(!user.can_perform_action(src, NEED_DEXTERITY)) - return ..() +/obj/item/clothing/suit/space/click_alt(mob/living/user) toggle_spacesuit_cell(user) + return CLICK_ACTION_SUCCESS /// Remove the cell whent he cover is open on CTRL+Click /obj/item/clothing/suit/space/CtrlClick(mob/living/user) diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index ce21351c885..02a54f194ea 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -87,9 +87,9 @@ else . += span_notice("There's nothing placed on the helmet.") -/obj/item/clothing/head/helmet/space/plasmaman/AltClick(mob/user) - if(user.can_perform_action(src)) - toggle_welding_screen(user) +/obj/item/clothing/head/helmet/space/plasmaman/click_alt(mob/user) + toggle_welding_screen(user) + return CLICK_ACTION_SUCCESS /obj/item/clothing/head/helmet/space/plasmaman/ui_action_click(mob/user, action) if(istype(action, /datum/action/item_action/toggle_welding_screen)) diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 02e6110b3ee..dcf6d502834 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -336,6 +336,40 @@ acid = 50 wound = 10 +/obj/item/clothing/suit/armor/balloon_vest + name = "balloon vest" + desc = "A vest made entirely from balloons, resistant to any evil forces a mime could throw at you, including electricity and fire. Just a strike with something sharp, though..." + icon_state = "balloon-vest" + inhand_icon_state = "balloon_armor" + blood_overlay_type = "armor" + armor_type = /datum/armor/balloon_vest + siemens_coefficient = 0 + strip_delay = 70 + equip_delay_other = 50 + +/datum/armor/balloon_vest + melee = 10 + laser = 10 + energy = 10 + fire = 60 + acid = 50 + +/obj/item/clothing/suit/armor/balloon_vest/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) + if(isitem(hitby)) + var/obj/item/item_hit = hitby + if(item_hit.sharpness) + pop() + + if(istype(hitby, /obj/projectile/bullet)) + pop() + + return ..() + +/obj/item/clothing/suit/armor/balloon_vest/proc/pop() + playsound(src, 'sound/effects/cartoon_pop.ogg', 50, vary = TRUE) + qdel(src) + + /obj/item/clothing/suit/armor/bulletproof name = "bulletproof armor" desc = "A Type III heavy bulletproof vest that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent." @@ -531,6 +565,16 @@ material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS//Can change color and add prefix armor_type = /datum/armor/knight_greyscale +/datum/armor/knight_greyscale + melee = 35 + bullet = 10 + laser = 10 + energy = 10 + bomb = 10 + bio = 10 + fire = 40 + acid = 40 + /obj/item/clothing/suit/armor/vest/durathread name = "durathread vest" desc = "A vest made of durathread with strips of leather acting as trauma plates." @@ -596,7 +640,7 @@ desc = "A superb armor made with the toughest and rarest materials available to man." icon_state = "h2armor" inhand_icon_state = null - material_flags = MATERIAL_EFFECTS | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS//Can change color and add prefix + material_flags = MATERIAL_EFFECTS | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS //Can change color and add prefix armor_type = /datum/armor/armor_elder_atmosian body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS diff --git a/code/modules/clothing/suits/wintercoats.dm b/code/modules/clothing/suits/wintercoats.dm index aaa233f0d35..a92811b0fe7 100644 --- a/code/modules/clothing/suits/wintercoats.dm +++ b/code/modules/clothing/suits/wintercoats.dm @@ -47,12 +47,7 @@ . += span_notice("Alt-click to [zipped ? "un" : ""]zip.") -/obj/item/clothing/suit/hooded/wintercoat/AltClick(mob/user) - . = ..() - - if (. == FALSE) // Direct check for FALSE, because that's the specific case we want to propagate, not just null. - return FALSE - +/obj/item/clothing/suit/hooded/wintercoat/click_alt(mob/user) zipped = !zipped worn_icon_state = "[initial(icon_state)][zipped ? "_t" : ""]" balloon_alert(user, "[zipped ? "" : "un"]zipped") @@ -60,6 +55,7 @@ if(ishuman(loc)) var/mob/living/carbon/human/wearer = loc wearer.update_worn_oversuit() + return CLICK_ACTION_SUCCESS /obj/item/clothing/head/hooded/winterhood name = "winter hood" diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm index 381415ba03e..1de7ed331e9 100644 --- a/code/modules/clothing/under/_under.dm +++ b/code/modules/clothing/under/_under.dm @@ -51,33 +51,37 @@ if(random_sensor) //make the sensor mode favor higher levels, except coords. sensor_mode = pick(SENSOR_VITALS, SENSOR_VITALS, SENSOR_VITALS, SENSOR_LIVING, SENSOR_LIVING, SENSOR_COORDS, SENSOR_COORDS, SENSOR_OFF) - register_context() + if(!unique_reskin) // Already registered via unique reskin + register_context() AddElement(/datum/element/update_icon_updates_onmob, flags = ITEM_SLOT_ICLOTHING|ITEM_SLOT_OCLOTHING, body = TRUE) -/obj/item/clothing/under/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) - . = NONE +/obj/item/clothing/under/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) + . = ..() + + var/changed = FALSE if(isnull(held_item) && has_sensor == HAS_SENSORS) context[SCREENTIP_CONTEXT_RMB] = "Toggle suit sensors" - . = CONTEXTUAL_SCREENTIP_SET + changed = TRUE if(istype(held_item, /obj/item/clothing/accessory) && length(attached_accessories) < max_number_of_accessories) context[SCREENTIP_CONTEXT_LMB] = "Attach accessory" - . = CONTEXTUAL_SCREENTIP_SET + changed = TRUE if(LAZYLEN(attached_accessories)) context[SCREENTIP_CONTEXT_ALT_RMB] = "Remove accessory" - . = CONTEXTUAL_SCREENTIP_SET + changed = TRUE if(istype(held_item, /obj/item/stack/cable_coil) && has_sensor == BROKEN_SENSORS) context[SCREENTIP_CONTEXT_LMB] = "Repair suit sensors" - . = CONTEXTUAL_SCREENTIP_SET + changed = TRUE if(can_adjust && adjusted != DIGITIGRADE_STYLE) context[SCREENTIP_CONTEXT_ALT_LMB] = "Wear [adjusted == ALT_STYLE ? "normally" : "casually"]" - . = CONTEXTUAL_SCREENTIP_SET + changed = TRUE + + return changed ? CONTEXTUAL_SCREENTIP_SET : NONE - return . /obj/item/clothing/under/worn_overlays(mutable_appearance/standing, isinhands = FALSE, file2use = null, mutant_styles = NONE) . = ..() @@ -353,17 +357,14 @@ BUBBERSTATION CHANGE END */ return TRUE -/obj/item/clothing/under/AltClick(mob/user) - . = ..() - if(.) - return - +/obj/item/clothing/under/click_alt(mob/user) if(!can_adjust) balloon_alert(user, "can't be adjusted!") - return + return CLICK_ACTION_BLOCKING if(!can_use(user)) - return + return NONE rolldown() + return CLICK_ACTION_SUCCESS /obj/item/clothing/under/alt_click_secondary(mob/user) . = ..() diff --git a/code/modules/clothing/under/costume.dm b/code/modules/clothing/under/costume.dm index 7f99a45c8b6..b09aaa34104 100644 --- a/code/modules/clothing/under/costume.dm +++ b/code/modules/clothing/under/costume.dm @@ -239,6 +239,7 @@ "Black" = "black_mech_suit", ) + /obj/item/clothing/under/costume/russian_officer name = "\improper Russian officer's uniform" desc = "The latest in fashionable russian outfits." diff --git a/code/modules/detectivework/evidence.dm b/code/modules/detectivework/evidence.dm index e22235084f9..c10648e3315 100644 --- a/code/modules/detectivework/evidence.dm +++ b/code/modules/detectivework/evidence.dm @@ -22,7 +22,7 @@ /obj/item/evidencebag/Exited(atom/movable/gone, direction) . = ..() cut_overlays() - w_class = initial(w_class) + update_weight_class(initial(w_class)) icon_state = initial(icon_state) desc = initial(desc) @@ -78,7 +78,7 @@ desc = "An evidence bag containing [I]. [I.desc]" I.forceMove(src) - w_class = I.w_class + update_weight_class(I.w_class) return 1 /obj/item/evidencebag/attack_self(mob/user) @@ -88,7 +88,7 @@ span_hear("You hear someone rustle around in a plastic bag, and remove something.")) cut_overlays() //remove the overlays user.put_in_hands(I) - w_class = WEIGHT_CLASS_TINY + update_weight_class(WEIGHT_CLASS_TINY) icon_state = "evidenceobj" desc = "An empty evidence bag." diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm index 6ce6b0e67a6..82c77839da7 100644 --- a/code/modules/detectivework/scanner.dm +++ b/code/modules/detectivework/scanner.dm @@ -218,20 +218,20 @@ /proc/get_timestamp() return time2text(world.time + 432000, ":ss") -/obj/item/detective_scanner/AltClick(mob/living/user) - // Best way for checking if a player can use while not incapacitated, etc - if(!user.can_perform_action(src)) - return +/obj/item/detective_scanner/click_alt(mob/living/user) if(!LAZYLEN(log)) balloon_alert(user, "no logs!") - return + return CLICK_ACTION_BLOCKING if(scanner_busy) balloon_alert(user, "scanner busy!") - return + return CLICK_ACTION_BLOCKING balloon_alert(user, "deleting logs...") - if(do_after(user, 3 SECONDS, target = src)) - balloon_alert(user, "logs cleared") - log = list() + if(!do_after(user, 3 SECONDS, target = src)) + return CLICK_ACTION_BLOCKING + balloon_alert(user, "logs cleared") + log = list() + return CLICK_ACTION_SUCCESS + /obj/item/detective_scanner/examine(mob/user) . = ..() diff --git a/code/modules/emoji/emoji_parse.dm b/code/modules/emoji/emoji_parse.dm index 533628eedf4..fa9b9ea0d5e 100644 --- a/code/modules/emoji/emoji_parse.dm +++ b/code/modules/emoji/emoji_parse.dm @@ -16,7 +16,7 @@ pos = search search = findtext(text, ":", pos + length(text[pos])) if(search) - emoji = lowertext(copytext(text, pos + length(text[pos]), search)) + emoji = LOWER_TEXT(copytext(text, pos + length(text[pos]), search)) var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/chat) var/tag = sheet.icon_tag("emoji-[emoji]") if(tag) @@ -46,9 +46,9 @@ pos = search search = findtext(text, ":", pos + length(text[pos])) if(search) - var/word = lowertext(copytext(text, pos + length(text[pos]), search)) + var/word = LOWER_TEXT(copytext(text, pos + length(text[pos]), search)) if(word in emojis) - final += lowertext(copytext(text, pos, search + length(text[search]))) + final += LOWER_TEXT(copytext(text, pos, search + length(text[search]))) pos = search + length(text[search]) continue break diff --git a/code/modules/escape_menu/home_page.dm b/code/modules/escape_menu/home_page.dm index 6d48285ae77..45180d98688 100644 --- a/code/modules/escape_menu/home_page.dm +++ b/code/modules/escape_menu/home_page.dm @@ -5,7 +5,7 @@ /* hud_owner = */ src, src, "Resume", - /* offset = */ 0, + /* offset = */ 1, CALLBACK(src, PROC_REF(home_resume)), ) ) @@ -16,7 +16,7 @@ /* hud_owner = */ null, src, "Settings", - /* offset = */ 1, + /* offset = */ 2, CALLBACK(src, PROC_REF(home_open_settings)), ) ) @@ -27,7 +27,7 @@ /* hud_owner = */ src, src, "Admin Help", - /* offset = */ 2, + /* offset = */ 3, ) ) //SKYRAT EDIT REMOVAL BEGIN @@ -38,7 +38,7 @@ /* hud_owner = */ src, src, "Leave Body", - /* offset = */ 3, + /* offset = */ 4, CALLBACK(src, PROC_REF(open_leave_body)), ) ) diff --git a/code/modules/events/vent_clog.dm b/code/modules/events/vent_clog.dm index c6f52ab50ca..fbd9b746d03 100644 --- a/code/modules/events/vent_clog.dm +++ b/code/modules/events/vent_clog.dm @@ -177,9 +177,9 @@ to_chat(user, span_notice("You cannot pump [vent] if it's welded shut!")) return - to_chat(user, span_notice("You begin pumping [vent] with your plunger.")) + user.balloon_alert_to_viewers("plunging vent...", "plunging clogged vent...") if(do_after(user, 6 SECONDS, target = vent)) - to_chat(user, span_notice("You finish pumping [vent].")) + user.balloon_alert_to_viewers("finished plunging") clear_signals() kill() diff --git a/code/modules/experisci/destructive_scanner.dm b/code/modules/experisci/destructive_scanner.dm index 5740b715bd4..d5d87eb6311 100644 --- a/code/modules/experisci/destructive_scanner.dm +++ b/code/modules/experisci/destructive_scanner.dm @@ -12,12 +12,8 @@ layer = MOB_LAYER var/scanning = FALSE -/obj/machinery/destructive_scanner/Initialize(mapload) - ..() - return INITIALIZE_HINT_LATELOAD - // Late load to ensure the component initialization occurs after the machines are initialized -/obj/machinery/destructive_scanner/LateInitialize() +/obj/machinery/destructive_scanner/post_machine_initialize() . = ..() var/static/list/destructive_signals = list( diff --git a/code/modules/experisci/experiment/handlers/experiment_handler.dm b/code/modules/experisci/experiment/handlers/experiment_handler.dm index e2d460e3903..b153c5157ea 100644 --- a/code/modules/experisci/experiment/handlers/experiment_handler.dm +++ b/code/modules/experisci/experiment/handlers/experiment_handler.dm @@ -238,6 +238,7 @@ /datum/component/experiment_handler/proc/configure_experiment(datum/source, mob/user) SIGNAL_HANDLER INVOKE_ASYNC(src, PROC_REF(ui_interact), user) + return CLICK_ACTION_SUCCESS /** * Attempts to show the user the experiment configuration panel diff --git a/code/modules/experisci/handheld_scanner.dm b/code/modules/experisci/handheld_scanner.dm index 32309336e3c..390937e0dd4 100644 --- a/code/modules/experisci/handheld_scanner.dm +++ b/code/modules/experisci/handheld_scanner.dm @@ -18,7 +18,6 @@ // Late initialize to allow for the rnd servers to initialize first /obj/item/experi_scanner/LateInitialize() - . = ..() var/static/list/handheld_signals = list( COMSIG_ITEM_PRE_ATTACK = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_handheld_experiment), COMSIG_ITEM_AFTERATTACK = TYPE_PROC_REF(/datum/component/experiment_handler, ignored_handheld_experiment_attempt), diff --git a/code/modules/explorer_drone/manager.dm b/code/modules/explorer_drone/manager.dm index 00909d03abf..ee51a2d5db3 100644 --- a/code/modules/explorer_drone/manager.dm +++ b/code/modules/explorer_drone/manager.dm @@ -83,11 +83,6 @@ . = ..() QDEL_NULL(temp_adventure) -/client/proc/adventure_manager() - set category = "Debug" - set name = "Adventure Manager" - - if(!check_rights(R_DEBUG)) - return +ADMIN_VERB(adventure_manager, R_DEBUG, "Adventure Manager", "View and edit adventures.", ADMIN_CATEGORY_DEBUG) var/datum/adventure_browser/browser = new() - browser.ui_interact(usr) + browser.ui_interact(user.mob) diff --git a/code/modules/explorer_drone/scanner_array.dm b/code/modules/explorer_drone/scanner_array.dm index 05f1d9a8b8f..6317ee273be 100644 --- a/code/modules/explorer_drone/scanner_array.dm +++ b/code/modules/explorer_drone/scanner_array.dm @@ -181,11 +181,7 @@ GLOBAL_LIST_INIT(scan_conditions,init_scan_conditions()) failed_popup = TRUE SStgui.update_uis(src) -/obj/machinery/computer/exoscanner_control/Initialize(mapload) - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/computer/exoscanner_control/LateInitialize() +/obj/machinery/computer/exoscanner_control/post_machine_initialize() . = ..() AddComponent(/datum/component/experiment_handler, \ allowed_experiments = list(/datum/experiment/exploration_scan), \ diff --git a/code/modules/fishing/admin.dm b/code/modules/fishing/admin.dm index d1d2c0ae2c5..0a9cfc9d51d 100644 --- a/code/modules/fishing/admin.dm +++ b/code/modules/fishing/admin.dm @@ -1,12 +1,6 @@ -// Helper tool to see fishing probabilities with different setups -/datum/admins/proc/fishing_calculator() - set name = "Fishing Calculator" - set category = "Debug" - - if(!check_rights(R_DEBUG)) - return - var/datum/fishing_calculator/ui = new(usr) - ui.ui_interact(usr) +ADMIN_VERB(fishing_calculator, R_DEBUG, "Fishing Calculator", "A calculator... for fishes?", ADMIN_CATEGORY_DEBUG) + var/datum/fishing_calculator/ui = new + ui.ui_interact(user.mob) /datum/fishing_calculator var/list/current_table diff --git a/code/modules/fishing/aquarium/aquarium.dm b/code/modules/fishing/aquarium/aquarium.dm index 48c7b8e24e9..8a719c16f70 100644 --- a/code/modules/fishing/aquarium/aquarium.dm +++ b/code/modules/fishing/aquarium/aquarium.dm @@ -159,10 +159,7 @@ if(panel_open && reagents.total_volume) . += span_notice("You can use a plunger to empty the feed storage.") -/obj/structure/aquarium/AltClick(mob/living/user) - . = ..() - if(!user.can_perform_action(src)) - return +/obj/structure/aquarium/click_alt(mob/living/user) panel_open = !panel_open balloon_alert(user, "panel [panel_open ? "open" : "closed"]") if(panel_open) @@ -170,6 +167,7 @@ else reagents.flags &= ~(TRANSPARENT|REFILLABLE) update_appearance() + return CLICK_ACTION_SUCCESS /obj/structure/aquarium/wrench_act(mob/living/user, obj/item/tool) . = ..() @@ -179,9 +177,9 @@ /obj/structure/aquarium/plunger_act(obj/item/plunger/P, mob/living/user, reinforced) if(!panel_open) return - to_chat(user, span_notice("You start plunging [name].")) + user.balloon_alert_to_viewers("plunging...") if(do_after(user, 3 SECONDS, target = src)) - to_chat(user, span_notice("You finish plunging the [name].")) + user.balloon_alert_to_viewers("finished plunging") reagents.expose(get_turf(src), TOUCH) //splash on the floor reagents.clear_reagents() diff --git a/code/modules/fishing/fish/_fish.dm b/code/modules/fishing/fish/_fish.dm index 85a387fd41d..62b302fb334 100644 --- a/code/modules/fishing/fish/_fish.dm +++ b/code/modules/fishing/fish/_fish.dm @@ -204,20 +204,20 @@ size = new_size switch(size) if(0 to FISH_SIZE_TINY_MAX) - w_class = WEIGHT_CLASS_TINY + update_weight_class(WEIGHT_CLASS_TINY) inhand_icon_state = "fish_small" if(FISH_SIZE_TINY_MAX to FISH_SIZE_SMALL_MAX) inhand_icon_state = "fish_small" - w_class = WEIGHT_CLASS_SMALL + update_weight_class(WEIGHT_CLASS_SMALL) if(FISH_SIZE_SMALL_MAX to FISH_SIZE_NORMAL_MAX) inhand_icon_state = "fish_normal" - w_class = WEIGHT_CLASS_NORMAL + update_weight_class(WEIGHT_CLASS_NORMAL) if(FISH_SIZE_NORMAL_MAX to FISH_SIZE_BULKY_MAX) inhand_icon_state = "fish_bulky" - w_class = WEIGHT_CLASS_BULKY + update_weight_class(WEIGHT_CLASS_BULKY) if(FISH_SIZE_BULKY_MAX to INFINITY) inhand_icon_state = "fish_huge" - w_class = WEIGHT_CLASS_HUGE + update_weight_class(WEIGHT_CLASS_HUGE) if(fillet_type) var/init_fillets = initial(num_fillets) var/amount = max(round(init_fillets * size / FISH_FILLET_NUMBER_SIZE_DIVISOR, 1), 1) diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm index 0578ffb0789..a0fa77dc514 100644 --- a/code/modules/fishing/fishing_rod.dm +++ b/code/modules/fishing/fishing_rod.dm @@ -234,7 +234,7 @@ cast_projectile.original = target cast_projectile.fired_from = src cast_projectile.firer = user - cast_projectile.impacted = list(user = TRUE) + cast_projectile.impacted = list(WEAKREF(user) = TRUE) cast_projectile.preparePixelProjectile(target, user) cast_projectile.fire() COOLDOWN_START(src, casting_cd, 1 SECONDS) diff --git a/code/modules/food_and_drinks/machinery/deep_fryer.dm b/code/modules/food_and_drinks/machinery/deep_fryer.dm index 140fde7e960..68cfddcf5f1 100644 --- a/code/modules/food_and_drinks/machinery/deep_fryer.dm +++ b/code/modules/food_and_drinks/machinery/deep_fryer.dm @@ -147,7 +147,11 @@ GLOBAL_LIST_INIT(oilfry_blacklisted_items, typecacheof(list( audible_message(span_notice("[src] dings!")) else if (cook_time >= DEEPFRYER_BURNTIME && !frying_burnt) frying_burnt = TRUE - visible_message(span_warning("[src] emits an acrid smell!")) + var/list/asomnia_hadders = list() + for(var/mob/smeller in get_hearers_in_view(DEFAULT_MESSAGE_RANGE, src)) + if(HAS_TRAIT(smeller, TRAIT_ANOSMIA)) + asomnia_hadders += smeller + visible_message(span_warning("[src] emits an acrid smell!"), ignored_mobs = asomnia_hadders) use_energy(active_power_usage) diff --git a/code/modules/food_and_drinks/machinery/food_cart.dm b/code/modules/food_and_drinks/machinery/food_cart.dm index e068b7b8ce2..a14ea3593c5 100644 --- a/code/modules/food_and_drinks/machinery/food_cart.dm +++ b/code/modules/food_and_drinks/machinery/food_cart.dm @@ -8,7 +8,7 @@ anchored = FALSE use_power = NO_POWER_USE req_access = list(ACCESS_KITCHEN) - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION + obj_flags = parent_type::obj_flags | NO_DEBRIS_AFTER_DECONSTRUCTION var/unpacked = FALSE var/obj/machinery/griddle/stand/cart_griddle var/obj/machinery/smartfridge/food/cart_smartfridge diff --git a/code/modules/food_and_drinks/machinery/griddle.dm b/code/modules/food_and_drinks/machinery/griddle.dm index b54a470897f..e0c45e6c9af 100644 --- a/code/modules/food_and_drinks/machinery/griddle.dm +++ b/code/modules/food_and_drinks/machinery/griddle.dm @@ -63,6 +63,7 @@ /obj/machinery/griddle/attackby(obj/item/I, mob/user, params) + if(griddled_objects.len >= max_items) to_chat(user, span_notice("[src] can't fit more items!")) return @@ -79,6 +80,43 @@ else return ..() +/obj/machinery/griddle/item_interaction_secondary(mob/living/user, obj/item/item, list/modifiers) + if(isnull(item.atom_storage)) + return NONE + + for(var/obj/tray_item in griddled_objects) + item.atom_storage.attempt_insert(tray_item, user, TRUE) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/griddle/item_interaction(mob/living/user, obj/item/item, list/modifiers) + if(isnull(item.atom_storage)) + return NONE + + if(length(contents) >= max_items) + balloon_alert(user, "it's full!") + return ITEM_INTERACT_BLOCKING + + if(!istype(item, /obj/item/storage/bag/tray)) + // Non-tray dumping requires a do_after + to_chat(user, span_notice("You start dumping out the contents of [item] into [src]...")) + if(!do_after(user, 2 SECONDS, target = item)) + return ITEM_INTERACT_BLOCKING + + var/loaded = 0 + for(var/obj/tray_item in item) + if(!IS_EDIBLE(tray_item)) + continue + if(length(contents) >= max_items) + break + if(item.atom_storage.attempt_remove(tray_item, src)) + loaded++ + AddToGrill(tray_item, user) + if(loaded) + to_chat(user, span_notice("You insert [loaded] item\s into [src].")) + update_appearance() + return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING + /obj/machinery/griddle/attack_hand(mob/user, list/modifiers) . = ..() toggle_mode() diff --git a/code/modules/food_and_drinks/machinery/grill.dm b/code/modules/food_and_drinks/machinery/grill.dm index 3d9acdde0ba..8d0aa921a7b 100644 --- a/code/modules/food_and_drinks/machinery/grill.dm +++ b/code/modules/food_and_drinks/machinery/grill.dm @@ -125,15 +125,15 @@ grill_fuel += boost update_appearance(UPDATE_ICON_STATE) -/obj/machinery/grill/item_interaction(mob/living/user, obj/item/weapon, list/modifiers, is_right_clicking) +/obj/machinery/grill/item_interaction(mob/living/user, obj/item/weapon, list/modifiers) if(user.combat_mode || (weapon.item_flags & ABSTRACT) || (weapon.flags_1 & HOLOGRAM_1) || (weapon.resistance_flags & INDESTRUCTIBLE)) - return ..() + return NONE if(istype(weapon, /obj/item/stack/sheet/mineral/coal) || istype(weapon, /obj/item/stack/sheet/mineral/wood)) if(!QDELETED(grilled_item)) - return ..() + return NONE if(!anchored) - balloon_alert(user, "anchor first!") + balloon_alert(user, "anchor it first!") return ITEM_INTERACT_BLOCKING //required for amount subtypes @@ -150,7 +150,7 @@ if(!istype(stored, target_type)) continue if(stored.amount == MAX_STACK_SIZE) - to_chat(user, span_warning("No space for [weapon]")) + balloon_alert(user, "no space!") return ITEM_INTERACT_BLOCKING target.merge(stored) merged = TRUE @@ -158,7 +158,7 @@ if(!merged) weapon.forceMove(src) - to_chat(user, span_notice("You add [src] to the fuel stack")) + to_chat(user, span_notice("You add [src] to the fuel stack.")) if(!grill_fuel) burn_stack() begin_processing() @@ -167,9 +167,9 @@ if(is_reagent_container(weapon) && weapon.is_open_container()) var/obj/item/reagent_containers/container = weapon if(!QDELETED(grilled_item)) - return ..() + return NONE if(!anchored) - balloon_alert(user, "anchor first!") + balloon_alert(user, "anchor it first!") return ITEM_INTERACT_BLOCKING var/transfered_amount = weapon.reagents.trans_to(src, container.amount_per_transfer_from_this) @@ -202,11 +202,11 @@ update_appearance(UPDATE_ICON_STATE) //feedback - to_chat(user, span_notice("You transfer [transfered_amount]u to the fuel source")) + 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 + + balloon_alert(user, "no fuel transfered!") + return ITEM_INTERACT_BLOCKING if(IS_EDIBLE(weapon)) //sanity checks @@ -218,10 +218,10 @@ if(!QDELETED(grilled_item)) balloon_alert(user, "remove item first!") return ITEM_INTERACT_BLOCKING - else if(grill_fuel <= 0) + if(grill_fuel <= 0) balloon_alert(user, "no fuel!") return ITEM_INTERACT_BLOCKING - else if(!user.transferItemToLoc(weapon, src)) + if(!user.transferItemToLoc(weapon, src)) balloon_alert(user, "[weapon] is stuck in your hand!") return ITEM_INTERACT_BLOCKING @@ -236,7 +236,7 @@ grill_loop.start() return ITEM_INTERACT_SUCCESS - return ..() + return NONE /obj/machinery/grill/wrench_act(mob/living/user, obj/item/tool) if(user.combat_mode) diff --git a/code/modules/food_and_drinks/machinery/icecream_vat.dm b/code/modules/food_and_drinks/machinery/icecream_vat.dm index d4de5991995..cae1b260249 100644 --- a/code/modules/food_and_drinks/machinery/icecream_vat.dm +++ b/code/modules/food_and_drinks/machinery/icecream_vat.dm @@ -154,13 +154,12 @@ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN return ..() -/obj/machinery/icecream_vat/AltClick(mob/user) - if(!user.can_interact_with(src)) - return FALSE - if(custom_ice_cream_beaker) - balloon_alert(user, "removed beaker") - try_put_in_hand(custom_ice_cream_beaker, user) - return ..() +/obj/machinery/icecream_vat/click_alt(mob/user) + if(!custom_ice_cream_beaker) + return CLICK_ACTION_BLOCKING + balloon_alert(user, "removed beaker") + try_put_in_hand(custom_ice_cream_beaker, user) + return CLICK_ACTION_SUCCESS /obj/machinery/icecream_vat/interact(mob/living/user) . = ..() diff --git a/code/modules/food_and_drinks/machinery/microwave.dm b/code/modules/food_and_drinks/machinery/microwave.dm index dfb6ac9b2de..55509886a3a 100644 --- a/code/modules/food_and_drinks/machinery/microwave.dm +++ b/code/modules/food_and_drinks/machinery/microwave.dm @@ -31,6 +31,7 @@ light_color = LIGHT_COLOR_DIM_YELLOW light_power = 3 anchored_tabletop_offset = 6 + interaction_flags_click = ALLOW_SILICON_REACH /// Is its function wire cut? var/wire_disabled = FALSE /// Wire cut to run mode backwards @@ -364,21 +365,15 @@ update_appearance() return ITEM_INTERACT_SUCCESS -/obj/machinery/microwave/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) +/obj/machinery/microwave/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(operating) - return + return ITEM_INTERACT_SKIP_TO_ATTACK // Don't use tools if we're dirty if(dirty >= MAX_MICROWAVE_DIRTINESS) - return - - . = ..() - if(. & ITEM_INTERACT_ANY_BLOCKER) - return . - + return ITEM_INTERACT_SKIP_TO_ATTACK // Don't insert items if we're dirty if(panel_open && is_wire_tool(tool)) wires.interact(user) return ITEM_INTERACT_SUCCESS - - return . + return NONE /obj/machinery/microwave/attackby(obj/item/item, mob/living/user, params) if(operating) @@ -473,16 +468,16 @@ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN -/obj/machinery/microwave/AltClick(mob/user, list/modifiers) - if(user.can_perform_action(src, ALLOW_SILICON_REACH)) - if(!vampire_charging_capable) - return +/obj/machinery/microwave/click_alt(mob/user, list/modifiers) + if(!vampire_charging_capable) + return NONE - vampire_charging_enabled = !vampire_charging_enabled - balloon_alert(user, "set to [vampire_charging_enabled ? "charge" : "cook"]") - playsound(src, 'sound/machines/twobeep_high.ogg', 50, FALSE) - if(HAS_SILICON_ACCESS(user)) - visible_message(span_notice("[user] sets \the [src] to [vampire_charging_enabled ? "charge" : "cook"]."), blind_message = span_notice("You hear \the [src] make an informative beep!")) + vampire_charging_enabled = !vampire_charging_enabled + balloon_alert(user, "set to [vampire_charging_enabled ? "charge" : "cook"]") + playsound(src, 'sound/machines/twobeep_high.ogg', 50, FALSE) + if(HAS_SILICON_ACCESS(user)) + visible_message(span_notice("[user] sets \the [src] to [vampire_charging_enabled ? "charge" : "cook"]."), blind_message = span_notice("You hear \the [src] make an informative beep!")) + return CLICK_ACTION_SUCCESS /obj/machinery/microwave/CtrlClick(mob/user) . = ..() diff --git a/code/modules/food_and_drinks/machinery/oven.dm b/code/modules/food_and_drinks/machinery/oven.dm index 517e25c6dcb..ef9aac9a410 100644 --- a/code/modules/food_and_drinks/machinery/oven.dm +++ b/code/modules/food_and_drinks/machinery/oven.dm @@ -90,20 +90,33 @@ baked_item.fire_act(1000) //Hot hot hot! if(SPT_PROB(10, seconds_per_tick)) - visible_message(span_danger("You smell a burnt smell coming from [src]!")) + var/list/asomnia_hadders = list() + for(var/mob/smeller in get_hearers_in_view(DEFAULT_MESSAGE_RANGE, src)) + if(HAS_TRAIT(smeller, TRAIT_ANOSMIA)) + asomnia_hadders += smeller + visible_message(span_danger("You smell a burnt smell coming from [src]!"), ignored_mobs = asomnia_hadders) set_smoke_state(worst_cooked_food_state) update_appearance() use_energy(active_power_usage) - -/obj/machinery/oven/attackby(obj/item/I, mob/user, params) - if(open && !used_tray && istype(I, /obj/item/plate/oven_tray)) - if(user.transferItemToLoc(I, src, silent = FALSE)) - to_chat(user, span_notice("You put [I] in [src].")) - add_tray_to_oven(I, user) - else +/obj/machinery/oven/attackby(obj/item/item, mob/user, params) + if(!open || used_tray || !istype(item, /obj/item/plate/oven_tray)) return ..() + if(user.transferItemToLoc(item, src, silent = FALSE)) + to_chat(user, span_notice("You put [item] in [src].")) + add_tray_to_oven(item, user) + +/obj/machinery/oven/item_interaction(mob/living/user, obj/item/item, list/modifiers) + if(open && used_tray && item.atom_storage) + return used_tray.item_interaction(user, item, modifiers) + return NONE + +/obj/machinery/oven/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers) + if(open && used_tray && tool.atom_storage) + return used_tray.item_interaction_secondary(user, tool, modifiers) + return NONE + ///Adds a tray to the oven, making sure the shit can get baked. /obj/machinery/oven/proc/add_tray_to_oven(obj/item/plate/oven_tray, mob/baker) used_tray = oven_tray @@ -239,6 +252,43 @@ max_items = 6 biggest_w_class = WEIGHT_CLASS_BULKY +/obj/item/plate/oven_tray/item_interaction_secondary(mob/living/user, obj/item/item, list/modifiers) + if(isnull(item.atom_storage)) + return NONE + + for(var/obj/tray_item in src) + item.atom_storage.attempt_insert(tray_item, user, TRUE) + return ITEM_INTERACT_SUCCESS + +/obj/item/plate/oven_tray/item_interaction(mob/living/user, obj/item/item, list/modifiers) + if(isnull(item.atom_storage)) + return NONE + + if(length(contents >= max_items)) + balloon_alert(user, "it's full!") + return ITEM_INTERACT_BLOCKING + + if(!istype(item, /obj/item/storage/bag/tray)) + // Non-tray dumping requires a do_after + to_chat(user, span_notice("You start dumping out the contents of [item] into [src]...")) + if(!do_after(user, 2 SECONDS, target = item)) + return ITEM_INTERACT_BLOCKING + + var/loaded = 0 + for(var/obj/tray_item in item) + if(!IS_EDIBLE(tray_item)) + continue + if(length(contents) >= max_items) + break + if(item.atom_storage.attempt_remove(tray_item, src)) + loaded++ + AddToPlate(tray_item, user) + if(loaded) + to_chat(user, span_notice("You insert [loaded] item\s into [src].")) + update_appearance() + return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING + #undef OVEN_SMOKE_STATE_NONE #undef OVEN_SMOKE_STATE_GOOD #undef OVEN_SMOKE_STATE_NEUTRAL diff --git a/code/modules/food_and_drinks/machinery/stove.dm b/code/modules/food_and_drinks/machinery/stove.dm index 38f98cfa8a8..6cc0ec52789 100644 --- a/code/modules/food_and_drinks/machinery/stove.dm +++ b/code/modules/food_and_drinks/machinery/stove.dm @@ -115,6 +115,34 @@ . = ..() LAZYREMOVE(added_ingredients, gone) +/** + * Adds items to a soup pot without invoking any procs that call sleep() when using in a component. + * + * Args: + * * transfer_from: The container that's being used to add items to the soup pot. Must not be null. + * * user: the entity adding ingredients via a container to a soup pot. Must not be null. + */ +/obj/item/reagent_containers/cup/soup_pot/proc/transfer_from_container_to_pot(obj/item/transfer_from, mob/user) + if(!transfer_from.atom_storage) + return + + var/obj/item/storage/tray = transfer_from + var/loaded = 0 + + for(var/obj/tray_item in tray.contents) + if(!can_add_ingredient(tray_item)) + continue + if(LAZYLEN(added_ingredients) >= max_ingredients) + balloon_alert(user, "it's full!") + return TRUE + if(tray.atom_storage.attempt_remove(tray_item, src)) + loaded++ + LAZYADD(added_ingredients, tray_item) + if(loaded) + to_chat(user, span_notice("You insert [loaded] items into \the [src].")) + update_appearance(UPDATE_OVERLAYS) + return TRUE + /obj/item/reagent_containers/cup/soup_pot/attackby(obj/item/attacking_item, mob/user, params) . = ..() if(.) @@ -140,6 +168,12 @@ update_appearance(UPDATE_OVERLAYS) return TRUE +/obj/item/reagent_containers/cup/soup_pot/item_interaction(mob/living/user, obj/item/item, list/modifiers) + if(LAZYACCESS(modifiers, RIGHT_CLICK)) + return NONE + + return transfer_from_container_to_pot(item, user) + /obj/item/reagent_containers/cup/soup_pot/attack_hand_secondary(mob/user, list/modifiers) if(!LAZYLEN(added_ingredients)) return SECONDARY_ATTACK_CALL_NORMAL diff --git a/code/modules/food_and_drinks/machinery/stove_component.dm b/code/modules/food_and_drinks/machinery/stove_component.dm index 1a39c3b2057..76a70f0f22a 100644 --- a/code/modules/food_and_drinks/machinery/stove_component.dm +++ b/code/modules/food_and_drinks/machinery/stove_component.dm @@ -128,6 +128,14 @@ /datum/component/stove/proc/on_attackby(obj/machinery/source, obj/item/attacking_item, mob/user, params) SIGNAL_HANDLER + if(istype(source, /obj/machinery/oven/range) && istype(attacking_item, /obj/item/storage/bag/tray) && container) + var/obj/machinery/oven/range/range = source + var/obj/item/reagent_containers/cup/soup_pot/soup_pot = container + + if(!range.open) + soup_pot.transfer_from_container_to_pot(attacking_item, user) + return COMPONENT_NO_AFTERATTACK + if(!attacking_item.is_open_container()) return if(!isnull(container)) diff --git a/code/modules/food_and_drinks/plate.dm b/code/modules/food_and_drinks/plate.dm index 1df1d7c24bb..4ae6bf19e1d 100644 --- a/code/modules/food_and_drinks/plate.dm +++ b/code/modules/food_and_drinks/plate.dm @@ -70,7 +70,7 @@ update_appearance() // If the incoming item is the same weight class as the plate, bump us up a class if(item_to_plate.w_class == w_class) - w_class += 1 + update_weight_class(w_class + 1) ///This proc cleans up any signals on the item when it is removed from a plate, and ensures it has the correct state again. /obj/item/plate/proc/ItemRemovedFromPlate(obj/item/removed_item) @@ -85,12 +85,14 @@ removed_item.pixel_z = 0 // We need to ensure the weight class is accurate now that we've lost something // that may or may not have been of equal weight - w_class = initial(w_class) + var/new_w_class = initial(w_class) for(var/obj/item/on_board in src) if(on_board.w_class == w_class) - w_class += 1 + new_w_class += 1 break + update_weight_class(new_w_class) + ///This proc is called by signals that remove the food from the plate. /obj/item/plate/proc/ItemMoved(obj/item/moved_item, atom/OldLoc, Dir, Forced) SIGNAL_HANDLER diff --git a/code/modules/food_and_drinks/recipes/food_mixtures.dm b/code/modules/food_and_drinks/recipes/food_mixtures.dm index c557f75a631..bada60cd548 100644 --- a/code/modules/food_and_drinks/recipes/food_mixtures.dm +++ b/code/modules/food_and_drinks/recipes/food_mixtures.dm @@ -280,8 +280,8 @@ reaction_flags = REACTION_INSTANT /datum/chemical_reaction/food/martian_batter - results = list(/datum/reagent/consumable/martian_batter = 2) - required_reagents = list(/datum/reagent/consumable/flour = 1, /datum/reagent/consumable/nutriment/soup/dashi = 1) + results = list(/datum/reagent/consumable/martian_batter = 10) + required_reagents = list(/datum/reagent/consumable/flour = 5, /datum/reagent/consumable/nutriment/soup/dashi = 5) mix_message = "A smooth batter forms." reaction_flags = REACTION_INSTANT diff --git a/code/modules/hallucination/fake_message.dm b/code/modules/hallucination/fake_message.dm index a1040496f5e..de5616d83c6 100644 --- a/code/modules/hallucination/fake_message.dm +++ b/code/modules/hallucination/fake_message.dm @@ -25,7 +25,7 @@ // in the future, this could / should be de-harcoded and // just draw from a pool uplink, theft, and antag item typepaths var/static/list/stash_item_paths = list( - /obj/item/areaeditor/blueprints, + /obj/item/blueprints, /obj/item/assembly/flash, /obj/item/card/id/advanced/gold/captains_spare, /obj/item/card/emag, diff --git a/code/modules/hallucination/inhand_fake_item.dm b/code/modules/hallucination/inhand_fake_item.dm index efea8b309e2..cb787d217e1 100644 --- a/code/modules/hallucination/inhand_fake_item.dm +++ b/code/modules/hallucination/inhand_fake_item.dm @@ -43,7 +43,7 @@ hallucinated_item.desc = initial(template_item_type.desc) hallucinated_item.icon = initial(template_item_type.icon) hallucinated_item.icon_state = initial(template_item_type.icon_state) - hallucinated_item.w_class = initial(template_item_type.w_class) // Not strictly necessary, but keen eyed people will notice + hallucinated_item.update_weight_class(initial(template_item_type.w_class)) // Not strictly necessary, but keen eyed people will notice return hallucinated_item diff --git a/code/modules/holodeck/computer.dm b/code/modules/holodeck/computer.dm index 7b4b23a313b..1ff5bc47a55 100644 --- a/code/modules/holodeck/computer.dm +++ b/code/modules/holodeck/computer.dm @@ -84,11 +84,8 @@ GLOBAL_LIST_INIT(typecache_holodeck_linked_floorcheck_ok, typecacheof(list(/turf //creates the timer that determines if another program can be manually loaded COOLDOWN_DECLARE(holodeck_cooldown) -/obj/machinery/computer/holodeck/Initialize(mapload) - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/computer/holodeck/LateInitialize()//from here linked is populated and the program list is generated. its also set to load the offline program +/obj/machinery/computer/holodeck/post_machine_initialize() //from here linked is populated and the program list is generated. its also set to load the offline program + . = ..() linked = GLOB.areas_by_type[mapped_start_area] if(!linked) log_mapping("[src] at [AREACOORD(src)] has no matching holodeck area.") @@ -295,12 +292,12 @@ GLOBAL_LIST_INIT(typecache_holodeck_linked_floorcheck_ok, typecacheof(list(/turf holo_object.resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF if(isstructure(holo_object)) - holo_object.obj_flags |= NO_DECONSTRUCTION + holo_object.obj_flags |= NO_DEBRIS_AFTER_DECONSTRUCTION return if(ismachinery(holo_object)) var/obj/machinery/holo_machine = holo_object - holo_machine.obj_flags |= NO_DECONSTRUCTION + holo_machine.obj_flags |= NO_DEBRIS_AFTER_DECONSTRUCTION holo_machine.power_change() if(istype(holo_machine, /obj/machinery/button)) diff --git a/code/modules/holodeck/holo_effect.dm b/code/modules/holodeck/holo_effect.dm index afd4c227038..caa5b425ca4 100644 --- a/code/modules/holodeck/holo_effect.dm +++ b/code/modules/holodeck/holo_effect.dm @@ -50,7 +50,7 @@ var/newtype = pick(subtypesof(/obj/item/book/manual) - banned_books) var/obj/item/book/manual/to_spawn = new newtype(loc) to_spawn.flags_1 |= HOLOGRAM_1 - to_spawn.obj_flags |= NO_DECONSTRUCTION + to_spawn.obj_flags |= NO_DEBRIS_AFTER_DECONSTRUCTION return to_spawn /obj/effect/holodeck_effect/mobspawner diff --git a/code/modules/holodeck/turfs.dm b/code/modules/holodeck/turfs.dm index 3e54c134106..51e09f8ab9a 100644 --- a/code/modules/holodeck/turfs.dm +++ b/code/modules/holodeck/turfs.dm @@ -8,9 +8,8 @@ /turf/open/floor/holofloor/attackby(obj/item/I, mob/living/user) return // HOLOFLOOR DOES NOT GIVE A FUCK -/turf/open/floor/holofloor/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) - SHOULD_CALL_PARENT(FALSE) - return NONE // Fuck you +/turf/open/floor/holofloor/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + return ITEM_INTERACT_BLOCKING // Fuck you /turf/open/floor/holofloor/burn_tile() return //you can't burn a hologram! diff --git a/code/modules/hydroponics/biogenerator.dm b/code/modules/hydroponics/biogenerator.dm index 260c4042a0a..35bf611b506 100644 --- a/code/modules/hydroponics/biogenerator.dm +++ b/code/modules/hydroponics/biogenerator.dm @@ -13,6 +13,7 @@ density = TRUE circuit = /obj/item/circuitboard/machine/biogenerator processing_flags = START_PROCESSING_MANUALLY + interaction_flags_click = FORBID_TELEKINESIS_REACH /// Whether the biogenerator is currently processing biomass or not. var/processing = FALSE /// The reagent container that is currently inside of the biomass generator. Can be null. @@ -272,10 +273,9 @@ to_chat(user, span_warning("You cannot put \the [attacking_item] in \the [src]!")) -/obj/machinery/biogenerator/AltClick(mob/living/user) - . = ..() - if(user.can_perform_action(src, FORBID_TELEKINESIS_REACH) && can_interact(user)) - eject_beaker(user) +/obj/machinery/biogenerator/click_alt(mob/living/user) + eject_beaker(user) + return CLICK_ACTION_SUCCESS /// Activates biomass processing and converts all inserted food products into biomass diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index ad12fa24e68..181a6fd9971 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -1099,8 +1099,6 @@ set_self_sustaining(!self_sustaining) to_chat(user, span_notice("You [self_sustaining ? "activate" : "deactivated"] [src]'s autogrow function[self_sustaining ? ", maintaining the tray's health while using high amounts of power" : ""].")) -/obj/machinery/hydroponics/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation /obj/machinery/hydroponics/attack_hand_secondary(mob/user, list/modifiers) . = ..() @@ -1159,7 +1157,6 @@ circuit = null density = FALSE use_power = NO_POWER_USE - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION unwrenchable = FALSE self_sustaining_overlay_icon_state = null maxnutri = 15 diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index 71fc93f8930..aa7c8e82222 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -246,7 +246,7 @@ else t_prod = new product(output_loc, new_seed = src) if(parent.myseed.plantname != initial(parent.myseed.plantname)) - t_prod.name = lowertext(parent.myseed.plantname) + t_prod.name = LOWER_TEXT(parent.myseed.plantname) if(productdesc) t_prod.desc = productdesc t_prod.seed.name = parent.myseed.name @@ -487,7 +487,7 @@ return if(!user.can_perform_action(src)) return - name = "[lowertext(newplantname)]" + name = "[LOWER_TEXT(newplantname)]" plantname = newplantname if("Seed Description") var/newdesc = tgui_input_text(user, "Write a new seed description", "Seed Description", desc, 180) diff --git a/code/modules/instruments/songs/play_legacy.dm b/code/modules/instruments/songs/play_legacy.dm index 7094de85a89..c49122d4641 100644 --- a/code/modules/instruments/songs/play_legacy.dm +++ b/code/modules/instruments/songs/play_legacy.dm @@ -9,7 +9,7 @@ var/list/octaves = list(3, 3, 3, 3, 3, 3, 3) var/list/accents = list("n", "n", "n", "n", "n", "n", "n") for(var/line in lines) - var/list/chords = splittext(lowertext(line), ",") + var/list/chords = splittext(LOWER_TEXT(line), ",") for(var/chord in chords) var/list/compiled_chord = list() var/tempodiv = 1 diff --git a/code/modules/instruments/songs/play_synthesized.dm b/code/modules/instruments/songs/play_synthesized.dm index 836c2fdd86b..05e23a8c97a 100644 --- a/code/modules/instruments/songs/play_synthesized.dm +++ b/code/modules/instruments/songs/play_synthesized.dm @@ -9,7 +9,7 @@ var/list/octaves = list(3, 3, 3, 3, 3, 3, 3) var/list/accents = list("n", "n", "n", "n", "n", "n", "n") for(var/line in lines) - var/list/chords = splittext(lowertext(line), ",") + var/list/chords = splittext(LOWER_TEXT(line), ",") for(var/chord in chords) var/list/compiled_chord = list() var/tempodiv = 1 diff --git a/code/modules/jobs/job_types/chaplain/chaplain.dm b/code/modules/jobs/job_types/chaplain/chaplain.dm index 58821ec5358..8bcfaefcfc6 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain.dm @@ -69,7 +69,7 @@ var/new_bible = player_client?.prefs?.read_preference(/datum/preference/name/bible) || DEFAULT_BIBLE holy_bible.deity_name = new_deity - switch(lowertext(new_religion)) + switch(LOWER_TEXT(new_religion)) if("homosexuality", "gay", "penis", "ass", "cock", "cocks") new_bible = pick("Guys Gone Wild","Coming Out of The Closet","War of Cocks") switch(new_bible) diff --git a/code/modules/jobs/job_types/clown.dm b/code/modules/jobs/job_types/clown.dm index 607c7214d90..58e7ad829bc 100644 --- a/code/modules/jobs/job_types/clown.dm +++ b/code/modules/jobs/job_types/clown.dm @@ -56,6 +56,7 @@ /obj/item/reagent_containers/spray/waterflower = 1, /obj/item/food/grown/banana = 1, /obj/item/instrument/bikehorn = 1, + /obj/item/storage/box/balloons = 1, ) belt = /obj/item/modular_computer/pda/clown ears = /obj/item/radio/headset/headset_srv @@ -71,6 +72,7 @@ box = /obj/item/storage/box/survival/hug chameleon_extras = /obj/item/stamp/clown implants = list(/obj/item/implant/sad_trombone) + skillchips = list(/obj/item/skillchip/job/clown) /datum/outfit/job/clown/mod name = "Clown (MODsuit)" diff --git a/code/modules/jobs/job_types/prisoner.dm b/code/modules/jobs/job_types/prisoner.dm index 9e09a7e81c0..f9d11a4817b 100644 --- a/code/modules/jobs/job_types/prisoner.dm +++ b/code/modules/jobs/job_types/prisoner.dm @@ -70,9 +70,9 @@ . = ..() var/crime_name = new_prisoner.client?.prefs?.read_preference(/datum/preference/choiced/prisoner_crime) - if(!crime_name) - return var/datum/prisoner_crime/crime = GLOB.prisoner_crimes[crime_name] + if (isnull(crime)) + return var/list/limbs_to_tat = new_prisoner.bodyparts.Copy() for(var/i in 1 to crime.tattoos) if(!length(SSpersistence.prison_tattoos_to_use) || visualsOnly) diff --git a/code/modules/jobs/jobs.dm b/code/modules/jobs/jobs.dm index 62a39d0c6f8..994d0d34c4c 100644 --- a/code/modules/jobs/jobs.dm +++ b/code/modules/jobs/jobs.dm @@ -65,7 +65,7 @@ GLOBAL_PROTECT(exp_specialmap) var/static/regex/chef_expand = new("chef") var/static/regex/borg_expand = new("(? owner.mob.see_invisible) + continue + + // convert + var/datum/search_object/index = new(owner, thing) + add_to_index(index) + + var/datum/tgui/window = SStgui.get_open_ui(owner.mob, src) + window?.send_update() + + if(length(to_image)) + SSlooting.backlog += src + + +/// For: Resetting to empty. Ignores the searchable qdel event +/datum/lootpanel/proc/reset_contents() + for(var/datum/search_object/index as anything in contents) + contents -= index + to_image -= index + + if(QDELETED(index)) + continue + + UnregisterSignal(index, COMSIG_QDELETING) + qdel(index) diff --git a/code/modules/lootpanel/handlers.dm b/code/modules/lootpanel/handlers.dm new file mode 100644 index 00000000000..40a76974ed4 --- /dev/null +++ b/code/modules/lootpanel/handlers.dm @@ -0,0 +1,19 @@ +/// On contents change, either reset or update +/datum/lootpanel/proc/on_searchable_deleted(datum/search_object/source) + SIGNAL_HANDLER + + contents -= source + to_image -= source + + var/datum/tgui/window = SStgui.get_open_ui(owner.mob, src) +#if !defined(UNIT_TESTS) // we dont want to delete contents if we're testing + if(isnull(window)) + reset_contents() + return +#endif + + if(isturf(source.item)) + populate_contents() + return + + window?.send_update() diff --git a/code/modules/lootpanel/misc.dm b/code/modules/lootpanel/misc.dm new file mode 100644 index 00000000000..6e8448b8205 --- /dev/null +++ b/code/modules/lootpanel/misc.dm @@ -0,0 +1,48 @@ +/// Helper to open the panel +/datum/lootpanel/proc/open(turf/tile) + source_turf = tile + +#if !defined(OPENDREAM) && !defined(UNIT_TESTS) + if(!notified) + var/build = owner.byond_build + var/version = owner.byond_version + if(build < 515 || (build == 515 && version < 1635)) + to_chat(owner.mob, examine_block(span_info("\ + Your version of Byond doesn't support fast image loading.\n\ + Detected: [version].[build]\n\ + Required version for this feature: 515.1635 or later.\n\ + Visit BYOND's website to get the latest version of BYOND.\n\ + "))) + + notified = TRUE +#endif + + populate_contents() + ui_interact(owner.mob) + + +/** + * Called by SSlooting whenever this datum is added to its backlog. + * Iterates over to_image list to create icons, then removes them. + * Returns boolean - whether this proc has finished the queue or not. + */ +/datum/lootpanel/proc/process_images() + for(var/datum/search_object/index as anything in to_image) + to_image -= index + + if(QDELETED(index) || index.icon) + continue + + index.generate_icon(owner) + + if(TICK_CHECK) + break + + var/datum/tgui/window = SStgui.get_open_ui(owner.mob, src) + if(isnull(window)) + reset_contents() + return TRUE + + window.send_update() + + return !length(to_image) diff --git a/code/modules/lootpanel/search_object.dm b/code/modules/lootpanel/search_object.dm new file mode 100644 index 00000000000..520228e465e --- /dev/null +++ b/code/modules/lootpanel/search_object.dm @@ -0,0 +1,84 @@ +/** + * ## Search Object + * An object for content lists. Compacted item data. + */ +/datum/search_object + /// Item we're indexing + var/atom/item + /// Url to the image of the object + var/icon + /// Icon state, for inexpensive icons + var/icon_state + /// Name of the original object + var/name + /// Typepath of the original object for ui grouping + var/path + + +/datum/search_object/New(client/owner, atom/item) + . = ..() + + src.item = item + name = item.name + if(isobj(item)) + path = item.type + + if(isturf(item)) + RegisterSignal(item, COMSIG_TURF_CHANGE, PROC_REF(on_turf_change)) + else + RegisterSignals(item, list( + COMSIG_ITEM_PICKUP, + COMSIG_MOVABLE_MOVED, + COMSIG_QDELETING, + ), PROC_REF(on_item_moved)) + + // Icon generation conditions ////////////// + // Condition 1: Icon is complex + if(ismob(item) || length(item.overlays) > 2) + return + + // Condition 2: Can't get icon path + if(!isfile(item.icon) || !length("[item.icon]")) + return + + // Condition 3: Using opendream +#if defined(OPENDREAM) || defined(UNIT_TESTS) + return +#endif + + // Condition 4: Using older byond version + var/build = owner.byond_build + var/version = owner.byond_version + if(build < 515 || (build == 515 && version < 1635)) + return + + icon = "[item.icon]" + icon_state = item.icon_state + + +/datum/search_object/Destroy(force) + item = null + + return ..() + + +/// Generates the icon for the search object. This is the expensive part. +/datum/search_object/proc/generate_icon(client/owner) + if(ismob(item) || length(item.overlays) > 2) + icon = costly_icon2html(item, owner, sourceonly = TRUE) + else // our pre 515.1635 fallback for normal items + icon = icon2html(item, owner, sourceonly = TRUE) + + +/// Parent item has been altered, search object no longer valid +/datum/search_object/proc/on_item_moved(atom/source) + SIGNAL_HANDLER + + qdel(src) + + +/// Parent tile has been altered, entire search needs reset +/datum/search_object/proc/on_turf_change(turf/source, path, list/new_baseturfs, flags, list/post_change_callbacks) + SIGNAL_HANDLER + + post_change_callbacks += CALLBACK(src, GLOBAL_PROC_REF(qdel), src) diff --git a/code/modules/lootpanel/ss_looting.dm b/code/modules/lootpanel/ss_looting.dm new file mode 100644 index 00000000000..cf0882fa890 --- /dev/null +++ b/code/modules/lootpanel/ss_looting.dm @@ -0,0 +1,39 @@ + +/// Queues image generation for search objects without icons +SUBSYSTEM_DEF(looting) + name = "Loot Icon Generation" + init_order = INIT_ORDER_LOOT + priority = FIRE_PRIORITY_PROCESS + wait = 0.5 SECONDS + /// Backlog of items. Gets put into processing + var/list/datum/lootpanel/backlog = list() + /// Actively processing items + var/list/datum/lootpanel/processing = list() + + +/datum/controller/subsystem/looting/stat_entry(msg) + msg = "P:[length(backlog)]" + return ..() + + +/datum/controller/subsystem/looting/fire(resumed) + if(!length(backlog)) + return + + if(!resumed) + processing = backlog + backlog = list() + + while(length(processing)) + var/datum/lootpanel/panel = processing[length(processing)] + if(QDELETED(panel) || !length(panel.to_image)) + processing.len-- + continue + + if(!panel.process_images()) + backlog += panel + + if(MC_TICK_CHECK) + return + + processing.len-- diff --git a/code/modules/lootpanel/ui.dm b/code/modules/lootpanel/ui.dm new file mode 100644 index 00000000000..c7f0cf2358d --- /dev/null +++ b/code/modules/lootpanel/ui.dm @@ -0,0 +1,42 @@ +/// UI helper for converting the associative list to a list of lists +/datum/lootpanel/proc/get_contents() + var/list/items = list() + + for(var/datum/search_object/index as anything in contents) + UNTYPED_LIST_ADD(items, list( + "icon_state" = index.icon_state, + "icon" = index.icon, + "name" = index.name, + "path" = index.path, + "ref" = REF(index), + )) + + return items + + +/// Clicks an object from the contents. Validates the object and the user +/datum/lootpanel/proc/grab(mob/user, list/params) + var/ref = params["ref"] + if(isnull(ref)) + return FALSE + + var/datum/search_object/index = locate(ref) in contents + var/atom/thing = index?.item + if(QDELETED(index) || QDELETED(thing)) // Obj is gone + return FALSE + + if(thing != source_turf && !(locate(thing) in source_turf.contents)) + qdel(index) // Item has moved + return TRUE + + var/modifiers = "" + if(params["ctrl"]) + modifiers += "ctrl=1;" + if(params["middle"]) + modifiers += "middle=1;" + if(params["shift"]) + modifiers += "shift=1;" + + user.ClickOn(thing, modifiers) + + return TRUE diff --git a/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm b/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm index 8a2949f9893..1c0a5392fb9 100644 --- a/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm +++ b/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm @@ -159,9 +159,14 @@ mask = /obj/item/clothing/mask/fakemoustache/italian /obj/machinery/vending/hotdog/museum - obj_flags = parent_type::obj_flags|NO_DECONSTRUCTION onstation_override = TRUE +/obj/machinery/vending/hotdog/museum/screwdriver_act(mob/living/user, obj/item/attack_item) + return NONE + +/obj/machinery/vending/hotdog/museum/crowbar_act(mob/living/user, obj/item/attack_item) + return NONE + #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. @@ -185,7 +190,6 @@ return INITIALIZE_HINT_LATELOAD /obj/item/keycard/cafeteria/LateInitialize() - . = ..() if(SSqueuelinks.queues[CAFE_KEYCARD_TOILETS]) SSqueuelinks.pop_link(CAFE_KEYCARD_TOILETS) diff --git a/code/modules/mapfluff/ruins/spaceruin_code/anomalyresearch.dm b/code/modules/mapfluff/ruins/spaceruin_code/anomalyresearch.dm index ba311d44a2a..f290c06d78f 100644 --- a/code/modules/mapfluff/ruins/spaceruin_code/anomalyresearch.dm +++ b/code/modules/mapfluff/ruins/spaceruin_code/anomalyresearch.dm @@ -17,7 +17,7 @@ /obj/effect/anomaly/flux, /obj/effect/anomaly/bluespace, /obj/effect/anomaly/hallucination, - /obj/effect/anomaly/bioscrambler + /obj/effect/anomaly/bioscrambler/docile ) ///Do we anchor the anomaly? Set to true if you don't want anomalies drifting away (like if theyre in space or something) diff --git a/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm index b61e14e8916..c699b25666e 100644 --- a/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm +++ b/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm @@ -363,20 +363,21 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999)) if(get_dist(get_turf(src), get_turf(user)) <= 1) promptExit(user) -/turf/closed/indestructible/hoteldoor/AltClick(mob/user) - . = ..() - if(get_dist(get_turf(src), get_turf(user)) <= 1) - to_chat(user, span_notice("You peak through the door's bluespace peephole...")) - user.reset_perspective(parentSphere) - var/datum/action/peephole_cancel/PHC = new - user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1) - PHC.Grant(user) - RegisterSignal(user, COMSIG_MOVABLE_MOVED, TYPE_PROC_REF(/atom/, check_eye), user) +/turf/closed/indestructible/hoteldoor/click_alt(mob/user) + to_chat(user, span_notice("You peak through the door's bluespace peephole...")) + user.reset_perspective(parentSphere) + var/datum/action/peephole_cancel/PHC = new + user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1) + PHC.Grant(user) + RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(check_eye)) + return CLICK_ACTION_SUCCESS -/turf/closed/indestructible/hoteldoor/check_eye(mob/user) - if(get_dist(get_turf(src), get_turf(user)) >= 2) - for(var/datum/action/peephole_cancel/PHC in user.actions) - INVOKE_ASYNC(PHC, TYPE_PROC_REF(/datum/action/peephole_cancel, Trigger)) +/turf/closed/indestructible/hoteldoor/proc/check_eye(mob/user, atom/oldloc, direction) + SIGNAL_HANDLER + if(get_dist(get_turf(src), get_turf(user)) < 2) + return + for(var/datum/action/peephole_cancel/PHC in user.actions) + INVOKE_ASYNC(PHC, TYPE_PROC_REF(/datum/action/peephole_cancel, Trigger)) /datum/action/peephole_cancel name = "Cancel View" diff --git a/code/modules/mapping/mail_sorting_helpers.dm b/code/modules/mapping/mail_sorting_helpers.dm index 964a4998600..259b9ef8f37 100644 --- a/code/modules/mapping/mail_sorting_helpers.dm +++ b/code/modules/mapping/mail_sorting_helpers.dm @@ -3,10 +3,6 @@ late = TRUE var/sort_type = SORT_TYPE_WASTE -/obj/effect/mapping_helpers/mail_sorting/Initialize(mapload) - ..() - return INITIALIZE_HINT_LATELOAD - /obj/effect/mapping_helpers/mail_sorting/LateInitialize() var/obj/structure/disposalpipe/sorting/mail/mail_sorter = locate(/obj/structure/disposalpipe/sorting/mail) in loc if(mail_sorter) diff --git a/code/modules/mapping/mapping_helpers.dm b/code/modules/mapping/mapping_helpers.dm index e601256a8b6..a2ffa244679 100644 --- a/code/modules/mapping/mapping_helpers.dm +++ b/code/modules/mapping/mapping_helpers.dm @@ -138,7 +138,6 @@ payload(airlock) /obj/effect/mapping_helpers/airlock/LateInitialize() - . = ..() var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in loc if(!airlock) qdel(src) @@ -283,7 +282,6 @@ return INITIALIZE_HINT_LATELOAD /obj/effect/mapping_helpers/airalarm/LateInitialize() - . = ..() var/obj/machinery/airalarm/target = locate(/obj/machinery/airalarm) in loc if(isnull(target)) @@ -442,7 +440,6 @@ return INITIALIZE_HINT_LATELOAD /obj/effect/mapping_helpers/apc/LateInitialize() - . = ..() var/obj/machinery/power/apc/target = locate(/obj/machinery/power/apc) in loc if(isnull(target)) @@ -1106,8 +1103,8 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava) */ /obj/effect/mapping_helpers/trapdoor_placer name = "trapdoor placer" - late = TRUE icon_state = "trapdoor" + late = TRUE /obj/effect/mapping_helpers/trapdoor_placer/LateInitialize() var/turf/component_target = get_turf(src) @@ -1187,12 +1184,8 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava) name = "broken floor" icon = 'icons/turf/damaged.dmi' icon_state = "damaged1" - late = TRUE layer = ABOVE_NORMAL_TURF_LAYER - -/obj/effect/mapping_helpers/broken_floor/Initialize(mapload) - .=..() - return INITIALIZE_HINT_LATELOAD + late = TRUE /obj/effect/mapping_helpers/broken_floor/LateInitialize() var/turf/open/floor/floor = get_turf(src) @@ -1203,12 +1196,8 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava) name = "burnt floor" icon = 'icons/turf/damaged.dmi' icon_state = "floorscorched1" - late = TRUE layer = ABOVE_NORMAL_TURF_LAYER - -/obj/effect/mapping_helpers/burnt_floor/Initialize(mapload) - .=..() - return INITIALIZE_HINT_LATELOAD + late = TRUE /obj/effect/mapping_helpers/burnt_floor/LateInitialize() var/turf/open/floor/floor = get_turf(src) @@ -1237,7 +1226,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava) return INITIALIZE_HINT_LATELOAD /obj/effect/mapping_helpers/broken_machine/LateInitialize() - . = ..() var/obj/machinery/target = locate(/obj/machinery) in loc if(isnull(target)) @@ -1271,7 +1259,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava) return INITIALIZE_HINT_LATELOAD /obj/effect/mapping_helpers/damaged_window/LateInitialize() - . = ..() var/obj/structure/window/target = locate(/obj/structure/window) in loc if(isnull(target)) @@ -1304,7 +1291,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava) return INITIALIZE_HINT_LATELOAD -/obj/effect/mapping_helpers/requests_console/LateInitialize(mapload) +/obj/effect/mapping_helpers/requests_console/LateInitialize() var/obj/machinery/airalarm/target = locate(/obj/machinery/requests_console) in loc if(isnull(target)) var/area/target_area = get_area(target) @@ -1441,7 +1428,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava) return INITIALIZE_HINT_QDEL /obj/effect/mapping_helpers/basic_mob_flags/LateInitialize() - . = ..() var/had_any_mobs = FALSE for(var/mob/living/basic/basic_mobs in loc) had_any_mobs = TRUE diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm index 5022dac212c..0b029bc3b63 100644 --- a/code/modules/mining/abandoned_crates.dm +++ b/code/modules/mining/abandoned_crates.dm @@ -60,10 +60,9 @@ return ..() -/obj/structure/closet/crate/secure/loot/AltClick(mob/living/user) - if(!user.can_perform_action(src)) - return - return attack_hand(user) //this helps you not blow up so easily by overriding unlocking which results in an immediate boom. +/obj/structure/closet/crate/secure/loot/click_alt(mob/living/user) + attack_hand(user) //this helps you not blow up so easily by overriding unlocking which results in an immediate boom. + return CLICK_ACTION_SUCCESS /obj/structure/closet/crate/secure/loot/attackby(obj/item/W, mob/user) if(locked) diff --git a/code/modules/mining/boulder_processing/_boulder_processing.dm b/code/modules/mining/boulder_processing/_boulder_processing.dm index 0dfc43cf7f7..5795eed1d74 100644 --- a/code/modules/mining/boulder_processing/_boulder_processing.dm +++ b/code/modules/mining/boulder_processing/_boulder_processing.dm @@ -38,7 +38,7 @@ register_context() -/obj/machinery/bouldertech/LateInitialize() +/obj/machinery/bouldertech/post_machine_initialize() . = ..() var/static/list/loc_connections = list( COMSIG_ATOM_ENTERED = PROC_REF(on_entered), @@ -244,9 +244,9 @@ return FALSE -/obj/machinery/bouldertech/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) +/obj/machinery/bouldertech/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(panel_open || user.combat_mode) - return ..() + return NONE if(istype(tool, /obj/item/boulder)) var/obj/item/boulder/my_boulder = tool @@ -276,7 +276,7 @@ to_chat(user, span_notice("You claim [amount] mining points from \the [src] to [id_card].")) return ITEM_INTERACT_SUCCESS - return ..() + return NONE /obj/machinery/bouldertech/wrench_act(mob/living/user, obj/item/tool) . = ITEM_INTERACT_BLOCKING diff --git a/code/modules/mining/boulder_processing/boulder_types.dm b/code/modules/mining/boulder_processing/boulder_types.dm index 08ed961404c..1ffce8737bd 100644 --- a/code/modules/mining/boulder_processing/boulder_types.dm +++ b/code/modules/mining/boulder_processing/boulder_types.dm @@ -44,7 +44,7 @@ /datum/material/uranium = 3, ) - set_custom_materials(list(pick_weight(gulag_minerals) = SHEET_MATERIAL_AMOUNT * rand(1, 3))) + set_custom_materials(list(pick_weight(gulag_minerals) = SHEET_MATERIAL_AMOUNT)) ///Boulders usually spawned in lavaland labour camp area but with bluespace material /obj/item/boulder/gulag_expanded @@ -66,7 +66,7 @@ /datum/material/uranium = 3, ) - set_custom_materials(list(pick_weight(expanded_gulag_minerals) = SHEET_MATERIAL_AMOUNT * rand(1, 3))) + set_custom_materials(list(pick_weight(expanded_gulag_minerals) = SHEET_MATERIAL_AMOUNT)) ///lowgrade boulder, most commonly spawned /obj/item/boulder/shabby diff --git a/code/modules/mining/boulder_processing/brm.dm b/code/modules/mining/boulder_processing/brm.dm index 259c3eed5f6..61c5469b459 100644 --- a/code/modules/mining/boulder_processing/brm.dm +++ b/code/modules/mining/boulder_processing/brm.dm @@ -101,7 +101,7 @@ if(default_deconstruction_crowbar(tool)) return ITEM_INTERACT_SUCCESS -///To allow boulders on a conveyer belt to move unobstructed if multiple machines are made on a single line +///To allow boulders on a conveyor belt to move unobstructed if multiple machines are made on a single line /obj/machinery/brm/CanAllowThrough(atom/movable/mover, border_dir) if(!anchored) return FALSE diff --git a/code/modules/mining/equipment/explorer_gear.dm b/code/modules/mining/equipment/explorer_gear.dm index 38df199b251..4845b0f9c00 100644 --- a/code/modules/mining/equipment/explorer_gear.dm +++ b/code/modules/mining/equipment/explorer_gear.dm @@ -90,7 +90,7 @@ /obj/item/clothing/mask/gas/explorer/adjustmask(mob/user) . = ..() // adjusted = out of the way = smaller = can fit in boxes - w_class = mask_adjusted ? WEIGHT_CLASS_SMALL : WEIGHT_CLASS_NORMAL + update_weight_class(mask_adjusted ? WEIGHT_CLASS_SMALL : WEIGHT_CLASS_NORMAL) inhand_icon_state = mask_adjusted ? "[initial(inhand_icon_state)]_up" : initial(inhand_icon_state) if(user) user.update_held_items() @@ -131,24 +131,25 @@ hoodtype = /obj/item/clothing/head/hooded/cloakhood/goliath body_parts_covered = CHEST|GROIN|ARMS -/obj/item/clothing/suit/hooded/cloak/goliath/AltClick(mob/user) - . = ..() - if(iscarbon(user)) - var/mob/living/carbon/char = user - if((char.get_item_by_slot(ITEM_SLOT_NECK) == src) || (char.get_item_by_slot(ITEM_SLOT_OCLOTHING) == src)) - to_chat(user, span_warning("You can't adjust [src] while wearing it!")) - return - if(!user.is_holding(src)) - to_chat(user, span_warning("You must be holding [src] in order to adjust it!")) - return - if(slot_flags & ITEM_SLOT_OCLOTHING) - slot_flags = ITEM_SLOT_NECK - set_armor(/datum/armor/none) - user.visible_message(span_notice("[user] adjusts their [src] for ceremonial use."), span_notice("You adjust your [src] for ceremonial use.")) - else - slot_flags = initial(slot_flags) - set_armor(initial(armor_type)) - user.visible_message(span_notice("[user] adjusts their [src] for defensive use."), span_notice("You adjust your [src] for defensive use.")) +/obj/item/clothing/suit/hooded/cloak/goliath/click_alt(mob/user) + if(!iscarbon(user)) + return NONE + var/mob/living/carbon/char = user + if((char.get_item_by_slot(ITEM_SLOT_NECK) == src) || (char.get_item_by_slot(ITEM_SLOT_OCLOTHING) == src)) + to_chat(user, span_warning("You can't adjust [src] while wearing it!")) + return CLICK_ACTION_BLOCKING + if(!user.is_holding(src)) + to_chat(user, span_warning("You must be holding [src] in order to adjust it!")) + return CLICK_ACTION_BLOCKING + if(slot_flags & ITEM_SLOT_OCLOTHING) + slot_flags = ITEM_SLOT_NECK + set_armor(/datum/armor/none) + user.visible_message(span_notice("[user] adjusts their [src] for ceremonial use."), span_notice("You adjust your [src] for ceremonial use.")) + else + slot_flags = initial(slot_flags) + set_armor(initial(armor_type)) + user.visible_message(span_notice("[user] adjusts their [src] for defensive use."), span_notice("You adjust your [src] for defensive use.")) + return CLICK_ACTION_SUCCESS /datum/armor/cloak_goliath melee = 35 @@ -353,4 +354,3 @@ desc = "An armoured hood for exploring harsh environments." icon_state = "explorer_syndicate" armor_type = /datum/armor/hooded_explorer_syndicate - diff --git a/code/modules/mining/equipment/grapple_gun.dm b/code/modules/mining/equipment/grapple_gun.dm new file mode 100644 index 00000000000..c7c91ede73e --- /dev/null +++ b/code/modules/mining/equipment/grapple_gun.dm @@ -0,0 +1,183 @@ +#define DAMAGE_ON_IMPACT 20 + +/obj/item/grapple_gun + name = "grapple gun" + desc = "A handy tool for traversing the land-scape of lava-land!" + icon = 'icons/obj/mining.dmi' + icon_state = "grapple_gun" + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + inhand_icon_state = "gun" + item_flags = NOBLUDGEON + ///overlay when the hook is retracted + var/static/mutable_appearance/hook_overlay = new(icon = 'icons/obj/mining.dmi', icon_state = "grapple_gun_hooked") + ///is the hook retracted + var/hooked = TRUE + ///addtimer id for launching the user + var/grapple_timer_id + ///traits we apply to the user when being launched + var/static/list/traits_on_zipline = list( + TRAIT_IMMOBILIZED, + TRAIT_MOVE_FLOATING, + TRAIT_FORCED_STANDING, + ) + ///the beam we draw + var/datum/beam/zipline + ///our user currently ziplining + var/datum/weakref/zipliner + ///ziplining sound + var/datum/looping_sound/zipline/zipline_sound + ///our initial matrix + var/matrix/initial_matrix + +/obj/item/grapple_gun/Initialize(mapload) + . = ..() + zipline_sound = new(src) + update_appearance() + +/obj/item/grapple_gun/afterattack(atom/target, mob/living/user, proximity) + . = ..() + + if(isgroundlessturf(target)) + return + + if(!lavaland_equipment_pressure_check(get_turf(user))) + user.balloon_alert(user, "gun mechanism wont work here!") + return + + if(target == user || !hooked) + return + + if(get_dist(user, target) > 9) + user.balloon_alert(user, "too far away!") + return + + var/turf/attacked_atom = get_turf(target) + if(isnull(attacked_atom)) + return + + var/list/turf_list = (get_line(user, attacked_atom) - get_turf(src)) + for(var/turf/singular_turf as anything in turf_list) + if(ischasm(singular_turf)) + continue + if(!singular_turf.is_blocked_turf()) + continue + attacked_atom = singular_turf + break + + if(user.CanReach(attacked_atom)) + return + + . |= AFTERATTACK_PROCESSED_ITEM + + var/atom/bullet = fire_projectile(/obj/projectile/grapple_hook, attacked_atom, 'sound/weapons/zipline_fire.ogg') + zipline = user.Beam(bullet, icon_state = "zipline_hook", maxdistance = 9, layer = BELOW_MOB_LAYER) + hooked = FALSE + RegisterSignal(bullet, COMSIG_PROJECTILE_SELF_ON_HIT, PROC_REF(on_grapple_hit)) + RegisterSignal(bullet, COMSIG_PREQDELETED, PROC_REF(on_grapple_fail)) + zipliner = WEAKREF(user) + update_appearance() + +/obj/item/grapple_gun/proc/on_grapple_hit(datum/source, atom/movable/firer, atom/target, Angle) + SIGNAL_HANDLER + + UnregisterSignal(source, list(COMSIG_PROJECTILE_ON_HIT, COMSIG_PREQDELETED)) + QDEL_NULL(zipline) + var/mob/living/user = zipliner?.resolve() + if(isnull(user) || isnull(target)) + cancel_hook() + return + + zipline = user.Beam(target, icon_state = "zipline_hook", maxdistance = 9, layer = BELOW_MOB_LAYER) + RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(determine_distance)) + RegisterSignal(user, COMSIG_MOVABLE_PRE_THROW, PROC_REF(apply_throw_traits)) + grapple_timer_id = addtimer(CALLBACK(src, PROC_REF(launch_user), target), 1.5 SECONDS, TIMER_STOPPABLE) + +/obj/item/grapple_gun/proc/on_grapple_fail(datum/source) + SIGNAL_HANDLER + cancel_hook() + +/obj/item/grapple_gun/proc/determine_distance(atom/movable/source) + SIGNAL_HANDLER + + if(isnull(zipline)) + return + var/atom/target = zipline.target + if(isnull(target)) + return + if(get_dist(source, target) > zipline.max_distance) + cancel_hook() + +/obj/item/grapple_gun/proc/apply_throw_traits(mob/living/source, list/arguements) + SIGNAL_HANDLER + var/atom/target_atom = arguements[1] + if(isnull(target_atom)) + return + var/dir_to_turn = get_angle(source, target_atom) + if(dir_to_turn > 175 && dir_to_turn < 190) + dir_to_turn = 0 + source.add_traits(traits_on_zipline, LEAPING_TRAIT) + initial_matrix = source.transform + animate(source, transform = matrix().Turn(dir_to_turn), time = 0.1 SECONDS) + +/obj/item/grapple_gun/proc/launch_user(atom/target_atom) + var/mob/living/my_user = zipliner?.resolve() + if(isnull(my_user) || isnull(target_atom) || my_user.buckled) + cancel_hook() + return + zipline_sound.start() + new /obj/effect/temp_visual/mook_dust(drop_location()) + RegisterSignal(my_user, COMSIG_MOVABLE_IMPACT, PROC_REF(strike_target)) + my_user.throw_at(target = target_atom, range = 9, speed = 1, spin = FALSE, gentle = TRUE, callback = CALLBACK(src, PROC_REF(post_land))) + +/obj/item/grapple_gun/proc/strike_target(mob/living/source, mob/living/victim, datum/thrownthing/throwingdatum) + SIGNAL_HANDLER + + if(!istype(victim)) + return + + victim.apply_damage(DAMAGE_ON_IMPACT) + playsound(victim, 'sound/effects/hit_kick.ogg', 50) + var/turf/target_turf = get_ranged_target_turf(victim, source.dir, 3) + if(isnull(target_turf)) + return + victim.throw_at(target = target_turf, speed = 1, spin = TRUE, range = 3) + + +/obj/item/grapple_gun/proc/post_land() + var/mob/living/my_user = zipliner?.resolve() + if(!isnull(my_user)) + my_user.transform = initial_matrix + my_user.remove_traits(traits_on_zipline, LEAPING_TRAIT) + new /obj/effect/temp_visual/mook_dust(drop_location()) + cancel_hook() + +/obj/item/grapple_gun/proc/cancel_hook() + var/atom/my_zipliner = zipliner?.resolve() + if(!isnull(my_zipliner)) + UnregisterSignal(my_zipliner, list(COMSIG_MOVABLE_IMPACT, COMSIG_MOVABLE_MOVED, COMSIG_MOVABLE_PRE_THROW)) + QDEL_NULL(zipline) + zipliner = null + if(grapple_timer_id) + deltimer(grapple_timer_id) + grapple_timer_id = null + hooked = TRUE + zipline_sound.stop() + initial_matrix = null + update_appearance() + +/obj/item/grapple_gun/update_overlays() + . = ..() + if(hooked) + . += hook_overlay + +/obj/projectile/grapple_hook + name = "grapple hook" + icon_state = "grapple_hook" + damage = 0 + range = 9 + speed = 0.1 + can_hit_turfs = TRUE + hitsound = 'sound/weapons/zipline_hit.ogg' + +#undef DAMAGE_ON_IMPACT diff --git a/code/modules/mining/equipment/marker_beacons.dm b/code/modules/mining/equipment/marker_beacons.dm index 38dda48d345..c33181dd806 100644 --- a/code/modules/mining/equipment/marker_beacons.dm +++ b/code/modules/mining/equipment/marker_beacons.dm @@ -43,7 +43,7 @@ GLOBAL_LIST_INIT(marker_beacon_colors, sort_list(list( "Alt-click to select a color. Current color is [picked_color]." /obj/item/stack/marker_beacon/update_icon_state() - icon_state = "[initial(icon_state)][lowertext(picked_color)]" + icon_state = "[initial(icon_state)][LOWER_TEXT(picked_color)]" return ..() /obj/item/stack/marker_beacon/attack_self(mob/user) @@ -59,16 +59,15 @@ GLOBAL_LIST_INIT(marker_beacon_colors, sort_list(list( var/obj/structure/marker_beacon/M = new(user.loc, picked_color) transfer_fingerprints_to(M) -/obj/item/stack/marker_beacon/AltClick(mob/living/user) - if(!istype(user) || !user.can_perform_action(src)) - return +/obj/item/stack/marker_beacon/click_alt(mob/living/user) var/input_color = tgui_input_list(user, "Choose a color", "Beacon Color", GLOB.marker_beacon_colors) if(isnull(input_color)) - return - if(!istype(user) || !user.can_perform_action(src)) - return + return CLICK_ACTION_BLOCKING + if(!user.can_perform_action(src)) + return CLICK_ACTION_BLOCKING picked_color = input_color update_appearance() + return CLICK_ACTION_SUCCESS /obj/structure/marker_beacon name = "marker beacon" @@ -116,7 +115,7 @@ GLOBAL_LIST_INIT(marker_beacon_colors, sort_list(list( set_light(light_range, light_power, GLOB.marker_beacon_colors[picked_color]) /obj/structure/marker_beacon/update_icon_state() - icon_state = "[icon_prefix][lowertext(picked_color)]-on" + icon_state = "[icon_prefix][LOWER_TEXT(picked_color)]-on" return ..() /obj/structure/marker_beacon/attack_hand(mob/living/user, list/modifiers) @@ -154,17 +153,15 @@ GLOBAL_LIST_INIT(marker_beacon_colors, sort_list(list( return return ..() -/obj/structure/marker_beacon/AltClick(mob/living/user) - ..() - if(!istype(user) || !user.can_perform_action(src)) - return +/obj/structure/marker_beacon/click_alt(mob/living/user) var/input_color = tgui_input_list(user, "Choose a color", "Beacon Color", GLOB.marker_beacon_colors) if(isnull(input_color)) - return - if(!istype(user) || !user.can_perform_action(src)) - return + return CLICK_ACTION_BLOCKING + if(!user.can_perform_action(src)) + return NONE picked_color = input_color update_appearance() + return CLICK_ACTION_SUCCESS /* Preset marker beacon types, for mapping */ diff --git a/code/modules/mining/equipment/mining_tools.dm b/code/modules/mining/equipment/mining_tools.dm index 9fdb772c4bc..4fdd997fcab 100644 --- a/code/modules/mining/equipment/mining_tools.dm +++ b/code/modules/mining/equipment/mining_tools.dm @@ -257,7 +257,7 @@ tool_behaviour = TOOL_WRENCH sharpness = NONE toolspeed = 0.75 - w_class = WEIGHT_CLASS_SMALL + update_weight_class(WEIGHT_CLASS_SMALL) usesound = 'sound/items/ratchet.ogg' attack_verb_continuous = list("bashes", "bludgeons", "thrashes", "whacks") attack_verb_simple = list("bash", "bludgeon", "thrash", "whack") @@ -265,7 +265,7 @@ tool_behaviour = TOOL_SHOVEL sharpness = SHARP_EDGED toolspeed = 0.25 - w_class = WEIGHT_CLASS_NORMAL + update_weight_class(WEIGHT_CLASS_NORMAL) usesound = 'sound/effects/shovel_dig.ogg' attack_verb_continuous = list("slashes", "impales", "stabs", "slices") attack_verb_simple = list("slash", "impale", "stab", "slice") @@ -273,7 +273,7 @@ tool_behaviour = TOOL_MINING sharpness = SHARP_POINTY toolspeed = 0.5 - w_class = WEIGHT_CLASS_NORMAL + update_weight_class(WEIGHT_CLASS_NORMAL) usesound = 'sound/effects/picaxe1.ogg' attack_verb_continuous = list("hits", "pierces", "slices", "attacks") attack_verb_simple = list("hit", "pierce", "slice", "attack") @@ -372,7 +372,7 @@ var/atom/throw_target = get_edge_target_turf(target_mob, get_dir(user, get_step_away(target_mob, user))) target_mob.throw_at(throw_target, 2, 2, user, gentle = TRUE) target_mob.Knockdown(2 SECONDS) - var/body_zone = pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) + var/body_zone = pick(GLOB.all_body_zones) user.apply_damage(force / recoil_factor, BRUTE, body_zone, user.run_armor_check(body_zone, MELEE)) to_chat(user, span_danger("The weight of the Big Slappy recoils!")) log_combat(user, user, "recoiled Big Slappy into") diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm index d40589dd3f8..b22603f52d9 100644 --- a/code/modules/mining/equipment/survival_pod.dm +++ b/code/modules/mining/equipment/survival_pod.dm @@ -249,7 +249,18 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/door/window/survival_pod/left, 0) light_color = COLOR_VERY_PALE_LIME_GREEN max_n_of_items = 10 pixel_y = -4 - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION + +/obj/machinery/smartfridge/survival_pod/welder_act(mob/living/user, obj/item/tool) + return NONE + +/obj/machinery/smartfridge/survival_pod/wrench_act(mob/living/user, obj/item/tool) + return NONE + +/obj/machinery/smartfridge/survival_pod/screwdriver_act(mob/living/user, obj/item/tool) + return NONE + +/obj/machinery/smartfridge/survival_pod/crowbar_act(mob/living/user, obj/item/tool) + return NONE /obj/machinery/smartfridge/survival_pod/Initialize(mapload) AddElement(/datum/element/update_icon_blocker) diff --git a/code/modules/mining/laborcamp/laborstacker.dm b/code/modules/mining/laborcamp/laborstacker.dm index 8a7ffeec88f..f46c7ecebb9 100644 --- a/code/modules/mining/laborcamp/laborstacker.dm +++ b/code/modules/mining/laborcamp/laborstacker.dm @@ -1,4 +1,4 @@ -GLOBAL_LIST(labor_sheet_values) +#define SHEET_POINT_VALUE 33 /**********************Prisoners' Console**************************/ @@ -22,14 +22,6 @@ GLOBAL_LIST(labor_sheet_values) if(!stacking_machine) return INITIALIZE_HINT_QDEL - if(!GLOB.labor_sheet_values) - var/sheet_list = list() - for(var/obj/item/stack/sheet/sheet as anything in subtypesof(/obj/item/stack/sheet)) - if(!initial(sheet.point_value) || (initial(sheet.merge_type) && initial(sheet.merge_type) != sheet)) //ignore no-value sheets and x/fifty subtypes - continue - sheet_list += list(list("ore" = initial(sheet.name), "value" = initial(sheet.point_value))) - GLOB.labor_sheet_values = sort_list(sheet_list, GLOBAL_PROC_REF(cmp_sheet_list)) - /obj/machinery/mineral/labor_claim_console/Destroy() QDEL_NULL(security_radio) if(stacking_machine) @@ -46,11 +38,6 @@ GLOBAL_LIST(labor_sheet_values) ui = new(user, src, "LaborClaimConsole", name) ui.open() -/obj/machinery/mineral/labor_claim_console/ui_static_data(mob/user) - var/list/data = list() - data["ores"] = GLOB.labor_sheet_values - return data - /obj/machinery/mineral/labor_claim_console/ui_data(mob/user) var/list/data = list() var/can_go_home = FALSE @@ -155,8 +142,9 @@ GLOBAL_LIST(labor_sheet_values) labor_console = null return ..() -/obj/machinery/mineral/stacking_machine/laborstacker/process_sheet(obj/item/stack/sheet/inp) - points += inp.point_value * inp.amount +/obj/machinery/mineral/stacking_machine/laborstacker/process_sheet(obj/item/stack/sheet/input) + if (input.manufactured && input.gulag_valid) + points += SHEET_POINT_VALUE * input.amount return ..() /obj/machinery/mineral/stacking_machine/laborstacker/attackby(obj/item/weapon, mob/user, params) @@ -190,3 +178,5 @@ GLOBAL_LIST(labor_sheet_values) say("ID: [prisoner_id.registered_name].") say("Points Collected: [prisoner_id.points] / [prisoner_id.goal].") say("Collect points by bringing smelted minerals to the Labor Shuttle stacking machine. Reach your quota to earn your release.") + +#undef SHEET_POINT_VALUE diff --git a/code/modules/mining/lavaland/megafauna_loot.dm b/code/modules/mining/lavaland/megafauna_loot.dm index 25214d2ae54..d0e5e08e15d 100644 --- a/code/modules/mining/lavaland/megafauna_loot.dm +++ b/code/modules/mining/lavaland/megafauna_loot.dm @@ -291,7 +291,10 @@ if(prob(7.5)) wearer.cause_hallucination(/datum/hallucination/oh_yeah, "H.E.C.K suit", haunt_them = TRUE) else - to_chat(wearer, span_warning("[pick("You hear faint whispers.","You smell ash.","You feel hot.","You hear a roar in the distance.")]")) + if(HAS_TRAIT(wearer, TRAIT_ANOSMIA)) //Anosmia quirk holder cannot fell any smell + to_chat(wearer, span_warning("[pick("You hear faint whispers.","You feel hot.","You hear a roar in the distance.")]")) + else + to_chat(wearer, span_warning("[pick("You hear faint whispers.","You smell ash.","You feel hot.","You hear a roar in the distance.")]")) /obj/item/clothing/head/hooded/hostile_environment name = "H.E.C.K. helmet" diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm index 11a941c4098..61318f63b92 100644 --- a/code/modules/mining/machine_processing.dm +++ b/code/modules/mining/machine_processing.dm @@ -143,6 +143,8 @@ var/datum/proximity_monitor/proximity_monitor ///Material container for materials var/datum/component/material_container/materials + /// What can be input into the machine? + var/accepted_type = /obj/item/stack /obj/machinery/mineral/processing_unit/Initialize(mapload) . = ..() @@ -153,7 +155,7 @@ SSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ INFINITY, \ MATCONTAINER_EXAMINE, \ - allowed_items = /obj/item/stack \ + allowed_items = accepted_type \ ) if(!GLOB.autounlock_techwebs[/datum/techweb/autounlocking/smelter]) GLOB.autounlock_techwebs[/datum/techweb/autounlocking/smelter] = new /datum/techweb/autounlocking/smelter @@ -166,7 +168,7 @@ stored_research = null return ..() -/obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/stack/ore/O) +/obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/stack/O) if(QDELETED(O)) return var/material_amount = materials.get_item_material_amount(O) @@ -225,7 +227,7 @@ /obj/machinery/mineral/processing_unit/pickup_item(datum/source, atom/movable/target, direction) if(QDELETED(target)) return - if(istype(target, /obj/item/stack/ore)) + if(istype(target, accepted_type)) process_ore(target) /obj/machinery/mineral/processing_unit/process(seconds_per_tick) @@ -282,4 +284,8 @@ var/O = new P(src) unload_mineral(O) +/// Only accepts ore, for the work camp +/obj/machinery/mineral/processing_unit/gulag + accepted_type = /obj/item/stack/ore + #undef SMELT_AMOUNT diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm index 0b9b7895c6b..14460cffb1b 100644 --- a/code/modules/mining/machine_redemption.dm +++ b/code/modules/mining/machine_redemption.dm @@ -203,18 +203,16 @@ default_unfasten_wrench(user, tool) return ITEM_INTERACT_SUCCESS -/obj/machinery/mineral/ore_redemption/AltClick(mob/living/user) - . = ..() - if(!user.can_perform_action(src)) - return - if(panel_open) - input_dir = turn(input_dir, -90) - output_dir = turn(output_dir, -90) - to_chat(user, span_notice("You change [src]'s I/O settings, setting the input to [dir2text(input_dir)] and the output to [dir2text(output_dir)].")) - unregister_input_turf() // someone just rotated the input and output directions, unregister the old turf - register_input_turf() // register the new one - update_appearance(UPDATE_OVERLAYS) - return TRUE +/obj/machinery/mineral/ore_redemption/click_alt(mob/living/user) + if(!panel_open) + return CLICK_ACTION_BLOCKING + input_dir = turn(input_dir, -90) + output_dir = turn(output_dir, -90) + to_chat(user, span_notice("You change [src]'s I/O settings, setting the input to [dir2text(input_dir)] and the output to [dir2text(output_dir)].")) + unregister_input_turf() // someone just rotated the input and output directions, unregister the old turf + register_input_turf() // register the new one + update_appearance(UPDATE_OVERLAYS) + return CLICK_ACTION_SUCCESS /obj/machinery/mineral/ore_redemption/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) diff --git a/code/modules/mining/machine_stacking.dm b/code/modules/mining/machine_stacking.dm index 286317a5d74..1f9a29a6e37 100644 --- a/code/modules/mining/machine_stacking.dm +++ b/code/modules/mining/machine_stacking.dm @@ -137,26 +137,26 @@ if (input_dir == output_dir) rotate(input) -/obj/machinery/mineral/stacking_machine/proc/process_sheet(obj/item/stack/sheet/inp) - if(QDELETED(inp)) +/obj/machinery/mineral/stacking_machine/proc/process_sheet(obj/item/stack/sheet/input) + if(QDELETED(input)) return // Dump the sheets to the silo if attached if(materials.silo && !materials.on_hold()) - var/matlist = inp.custom_materials & materials.mat_container.materials + var/matlist = input.custom_materials & materials.mat_container.materials if (length(matlist)) - materials.mat_container.insert_item(inp, context = src) + materials.insert_item(input) return // No silo attached process to internal storage - var/key = inp.merge_type + var/key = input.merge_type var/obj/item/stack/sheet/storage = stack_list[key] if(!storage) //It's the first of this sheet added - stack_list[key] = storage = new inp.type(src, 0) - storage.amount += inp.amount //Stack the sheets - qdel(inp) + stack_list[key] = storage = new input.type(src, 0) + storage.amount += input.amount //Stack the sheets + qdel(input) while(storage.amount >= stack_amt) //Get rid of excessive stackage - var/obj/item/stack/sheet/out = new inp.type(null, stack_amt) + var/obj/item/stack/sheet/out = new input.type(null, stack_amt) unload_mineral(out) storage.amount -= stack_amt diff --git a/code/modules/mob/dead/observer/observer_say.dm b/code/modules/mob/dead/observer/observer_say.dm index e43086349b3..a8fd0094934 100644 --- a/code/modules/mob/dead/observer/observer_say.dm +++ b/code/modules/mob/dead/observer/observer_say.dm @@ -5,7 +5,7 @@ /mob/dead/observer/get_message_mods(message, list/mods) var/key = message[1] if((key in GLOB.department_radio_prefixes) && length(message) > length(key) + 1 && !mods[RADIO_EXTENSION]) - mods[RADIO_KEY] = lowertext(message[1 + length(key)]) + mods[RADIO_KEY] = LOWER_TEXT(message[1 + length(key)]) mods[RADIO_EXTENSION] = GLOB.department_radio_keys[mods[RADIO_KEY]] return message @@ -44,9 +44,9 @@ message = trim_left(copytext_char(message, length(message_mods[RADIO_KEY]) + 2)) switch(message_mods[RADIO_EXTENSION]) if(MODE_ADMIN) - client.cmd_admin_say(message) + SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/cmd_admin_say, message) if(MODE_DEADMIN) - client.dsay(message) + SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/dsay, message) if(MODE_PUPPET) if(!mind.current.say(message)) to_chat(src, span_warning("Your linked body was unable to speak!")) diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index bf9e099e5c9..c1822ff0e51 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -19,7 +19,7 @@ param = copytext(act, custom_param + length(act[custom_param])) act = copytext(act, 1, custom_param) - act = lowertext(act) + act = LOWER_TEXT(act) var/list/key_emotes = GLOB.emote_list[act] if(!length(key_emotes)) diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm index 8dccd198f26..6e42d2adc97 100644 --- a/code/modules/mob/living/basic/basic.dm +++ b/code/modules/mob/living/basic/basic.dm @@ -121,6 +121,7 @@ return apply_atmos_requirements(mapload) apply_temperature_requirements(mapload) + apply_target_randomisation() /mob/living/basic/proc/on_ssair_init(datum/source) SIGNAL_HANDLER @@ -142,6 +143,11 @@ return AddElement(/datum/element/body_temp_sensitive, minimum_survivable_temperature, maximum_survivable_temperature, unsuitable_cold_damage, unsuitable_heat_damage, mapload) +/mob/living/basic/proc/apply_target_randomisation() + if (basic_mob_flags & PRECISE_ATTACK_ZONES) + return + AddElement(/datum/element/attack_zone_randomiser) + /mob/living/basic/Life(seconds_per_tick = SSMOBS_DT, times_fired) . = ..() if(staminaloss > 0) diff --git a/code/modules/mob/living/basic/bots/_bots.dm b/code/modules/mob/living/basic/bots/_bots.dm index 206ba88b317..ccd4b0d617f 100644 --- a/code/modules/mob/living/basic/bots/_bots.dm +++ b/code/modules/mob/living/basic/bots/_bots.dm @@ -6,6 +6,8 @@ GLOBAL_LIST_INIT(command_strings, list( "home" = "RETURN HOME", )) +#define SENTIENT_BOT_RESET_TIMER 45 SECONDS + /mob/living/basic/bot icon = 'icons/mob/silicon/aibots.dmi' layer = MOB_LAYER @@ -39,6 +41,7 @@ GLOBAL_LIST_INIT(command_strings, list( light_power = 0.6 speed = 3 req_one_access = list(ACCESS_ROBOTICS) + interaction_flags_click = ALLOW_SILICON_REACH ///The Robot arm attached to this robot - has a 50% chance to drop on death. var/robot_arm = /obj/item/bodypart/arm/right/robot ///The inserted (if any) pAI in this bot. @@ -101,7 +104,7 @@ GLOBAL_LIST_INIT(command_strings, list( AddElement(/datum/element/relay_attackers) RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(handle_loop_movement)) RegisterSignal(src, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(after_attacked)) - RegisterSignal(src, COMSIG_MOB_TRIED_ACCESS, PROC_REF(attempt_access)) + RegisterSignal(src, COMSIG_OBJ_ALLOWED, PROC_REF(attempt_access)) ADD_TRAIT(src, TRAIT_NO_GLIDE, INNATE_TRAIT) GLOB.bots_list += src @@ -360,13 +363,9 @@ GLOBAL_LIST_INIT(command_strings, list( ui = new(user, src, "SimpleBot", name) ui.open() -/mob/living/basic/bot/AltClick(mob/user) - . = ..() - if(!can_interact(user)) - return - if(!user.can_perform_action(src, ALLOW_SILICON_REACH)) - return +/mob/living/basic/bot/click_alt(mob/user) unlock_with_id(user) + return CLICK_ACTION_SUCCESS /mob/living/basic/bot/proc/unlock_with_id(mob/living/user) if(bot_access_flags & BOT_COVER_EMAGGED) @@ -758,9 +757,7 @@ GLOBAL_LIST_INIT(command_strings, list( /mob/living/basic/bot/proc/attempt_access(mob/bot, obj/door_attempt) SIGNAL_HANDLER - if(door_attempt.check_access(access_card)) - return ACCESS_ALLOWED - return ACCESS_DISALLOWED + return (door_attempt.check_access(access_card) ? COMPONENT_OBJ_ALLOW : COMPONENT_OBJ_DISALLOW) /mob/living/basic/bot/proc/generate_speak_list() return null @@ -783,6 +780,8 @@ GLOBAL_LIST_INIT(command_strings, list( access_card.set_access(access_to_grant) speak("Responding.", radio_channel) update_bot_mode(new_mode = BOT_SUMMON) + if(client) //if we're sentient, we reset ourselves after a short period + addtimer(CALLBACK(src, PROC_REF(bot_reset)), SENTIENT_BOT_RESET_TIMER) return TRUE /mob/living/basic/bot/proc/set_ai_caller(mob/living/caller) @@ -809,3 +808,5 @@ GLOBAL_LIST_INIT(command_strings, list( /mob/living/basic/bot/proc/on_bot_movement(atom/movable/source, atom/oldloc, dir, forced) return + +#undef SENTIENT_BOT_RESET_TIMER diff --git a/code/modules/mob/living/basic/bots/bot_ai.dm b/code/modules/mob/living/basic/bots/bot_ai.dm index 36600f244e7..16ca5200308 100644 --- a/code/modules/mob/living/basic/bots/bot_ai.dm +++ b/code/modules/mob/living/basic/bots/bot_ai.dm @@ -34,6 +34,13 @@ if(. & AI_CONTROLLER_INCOMPATIBLE) return RegisterSignal(new_pawn, COMSIG_BOT_RESET, PROC_REF(reset_bot)) + RegisterSignal(new_pawn, COMSIG_AI_BLACKBOARD_KEY_CLEARED(BB_BOT_SUMMON_TARGET), PROC_REF(clear_summon)) + +/datum/ai_controller/basic_controller/bot/proc/clear_summon() + SIGNAL_HANDLER + + var/mob/living/basic/bot/bot_pawn = pawn + bot_pawn.bot_reset() /datum/ai_controller/basic_controller/bot/able_to_run() var/mob/living/basic/bot/bot_pawn = pawn diff --git a/code/modules/mob/living/basic/bots/medbot/medbot.dm b/code/modules/mob/living/basic/bots/medbot/medbot.dm index e784aa6249e..e76e723e197 100644 --- a/code/modules/mob/living/basic/bots/medbot/medbot.dm +++ b/code/modules/mob/living/basic/bots/medbot/medbot.dm @@ -7,14 +7,13 @@ icon_state = "medibot0" base_icon_state = "medibot" density = FALSE - anchored = FALSE health = 20 maxHealth = 20 speed = 2 light_power = 0.8 light_color = "#99ccff" pass_flags = PASSMOB | PASSFLAPS - status_flags = CANSTUN + status_flags = (CANPUSH | CANSTUN) ai_controller = /datum/ai_controller/basic_controller/bot/medbot req_one_access = list(ACCESS_ROBOTICS, ACCESS_MEDICAL) @@ -162,7 +161,6 @@ return INITIALIZE_HINT_LATELOAD /mob/living/basic/bot/medbot/LateInitialize() - . = ..() if(!CONFIG_GET(flag/no_default_techweb_link) && !linked_techweb) CONNECT_TO_RND_SERVER_ROUNDSTART(linked_techweb, src) diff --git a/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm b/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm index 21169ffd368..61f31f7044d 100644 --- a/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm +++ b/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm @@ -44,7 +44,7 @@ StartCooldown() return TRUE - do_after(owner, delay = beam_duration, target = owner) + do_after(owner, delay = beam_duration, target = owner, hidden = TRUE) extinguish_laser() StartCooldown() return TRUE diff --git a/code/modules/mob/living/basic/minebots/minebot.dm b/code/modules/mob/living/basic/minebots/minebot.dm index 26e549cbcf9..3361330915f 100644 --- a/code/modules/mob/living/basic/minebots/minebot.dm +++ b/code/modules/mob/living/basic/minebots/minebot.dm @@ -203,12 +203,12 @@ combat_overlay.color = selected_color update_appearance() -/mob/living/basic/mining_drone/AltClick(mob/living/user) - . = ..() +/mob/living/basic/mining_drone/click_alt(mob/living/user) if(user.combat_mode) - return + return CLICK_ACTION_BLOCKING set_combat_mode(!combat_mode) balloon_alert(user, "now [combat_mode ? "attacking wildlife" : "collecting loose ore"]") + return CLICK_ACTION_SUCCESS /mob/living/basic/mining_drone/RangedAttack(atom/target) if(!combat_mode) diff --git a/code/modules/mob/living/basic/ruin_defender/flesh.dm b/code/modules/mob/living/basic/ruin_defender/flesh.dm index a80d6847a8a..a6087f08589 100644 --- a/code/modules/mob/living/basic/ruin_defender/flesh.dm +++ b/code/modules/mob/living/basic/ruin_defender/flesh.dm @@ -38,6 +38,9 @@ if(!isnull(limb)) register_to_limb(limb) +/mob/living/basic/living_limb_flesh/apply_target_randomisation() + AddElement(/datum/element/attack_zone_randomiser, GLOB.limb_zones) + /mob/living/basic/living_limb_flesh/Destroy(force) . = ..() if(current_bodypart) @@ -71,6 +74,8 @@ if(!victim.CanReach(movable)) continue candidates += movable + if(!length(candidates)) + return var/atom/movable/candidate = pick(candidates) if(isnull(candidate)) return @@ -123,9 +128,9 @@ part_type = /obj/item/bodypart/leg/right/flesh target.visible_message(span_danger("[src] [target_part ? "tears off and attaches itself" : "attaches itself"] to where [target][target.p_s()] limb used to be!")) - var/obj/item/bodypart/new_bodypart = new part_type(TRUE) //dont_spawn_flesh, we cant use named arguments here - new_bodypart.replace_limb(target, TRUE) + var/obj/item/bodypart/new_bodypart = new part_type() forceMove(new_bodypart) + new_bodypart.replace_limb(target, TRUE) register_to_limb(new_bodypart) /mob/living/basic/living_limb_flesh/proc/owner_shocked(datum/source, shock_damage, shock_source, siemens_coeff, flags) diff --git a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm index 51379ce88a0..c0fb9b67e7f 100644 --- a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm +++ b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm @@ -55,6 +55,7 @@ AddElementTrait(TRAIT_WADDLING, INNATE_TRAIT, /datum/element/waddling) AddElement(/datum/element/ai_retaliate) AddElement(/datum/element/door_pryer, pry_time = 5 SECONDS, interaction_key = REGALRAT_INTERACTION) + AddElement(/datum/element/poster_tearer, interaction_key = REGALRAT_INTERACTION) AddComponent(\ /datum/component/ghost_direct_control,\ poll_candidates = poll_ghosts,\ diff --git a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm index 266e7b5b414..21943d39d3d 100644 --- a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm +++ b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm @@ -204,7 +204,7 @@ ShiftClickOn(A) return if(LAZYACCESS(modifiers, ALT_CLICK)) - AltClickNoInteract(src, A) + base_click_alt(A) return if(LAZYACCESS(modifiers, RIGHT_CLICK)) ranged_secondary_attack(A, modifiers) diff --git a/code/modules/mob/living/basic/trooper/syndicate.dm b/code/modules/mob/living/basic/trooper/syndicate.dm index c4d1bbd3630..8f8d564693b 100644 --- a/code/modules/mob/living/basic/trooper/syndicate.dm +++ b/code/modules/mob/living/basic/trooper/syndicate.dm @@ -154,6 +154,13 @@ ranged_cooldown = 3 SECONDS r_hand = /obj/item/gun/ballistic/automatic/c20r +///Spawns from an emagged orion trail machine set to kill the player. +/mob/living/basic/trooper/syndicate/ranged/smg/orion + name = "spaceport security" + desc = "Premier corporate security forces for all spaceports found along the Orion Trail." + faction = list(FACTION_ORION) + loot = list() + /mob/living/basic/trooper/syndicate/ranged/smg/pilot //caravan ambush ruin name = "Syndicate Salvage Pilot" loot = list(/obj/effect/mob_spawn/corpse/human/syndicatepilot) diff --git a/code/modules/mob/living/brain/posibrain.dm b/code/modules/mob/living/brain/posibrain.dm index 038763e0360..d90db60a473 100644 --- a/code/modules/mob/living/brain/posibrain.dm +++ b/code/modules/mob/living/brain/posibrain.dm @@ -75,17 +75,16 @@ GLOBAL_VAR(posibrain_notify_cooldown) update_appearance() addtimer(CALLBACK(src, PROC_REF(check_success)), ask_delay) -/obj/item/mmi/posibrain/AltClick(mob/living/user) - if(!istype(user) || !user.can_perform_action(src)) - return +/obj/item/mmi/posibrain/click_alt(mob/living/user) var/input_seed = tgui_input_text(user, "Enter a personality seed", "Enter seed", ask_role, MAX_NAME_LEN) if(isnull(input_seed)) - return - if(!istype(user) || !user.can_perform_action(src)) + return CLICK_ACTION_BLOCKING + if(!user.can_perform_action(src)) return to_chat(user, span_notice("You set the personality seed to \"[input_seed]\".")) ask_role = input_seed update_appearance() + return CLICK_ACTION_SUCCESS /obj/item/mmi/posibrain/proc/check_success() searching = FALSE diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 982613f331c..97a222cdd95 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -240,25 +240,34 @@ return TRUE return FALSE + /mob/living/carbon/resist_buckle() - if(HAS_TRAIT(src, TRAIT_RESTRAINED)) - changeNext_move(CLICK_CD_BREAKOUT) - last_special = world.time + CLICK_CD_BREAKOUT - var/buckle_cd = 60 SECONDS - if(handcuffed) - var/obj/item/restraints/O = src.get_item_by_slot(ITEM_SLOT_HANDCUFFED) - buckle_cd = O.breakouttime - visible_message(span_warning("[src] attempts to unbuckle [p_them()]self!"), \ - span_notice("You attempt to unbuckle yourself... (This will take around [round(buckle_cd/600,1)] minute\s, and you need to stay still.)")) - if(do_after(src, buckle_cd, target = src, timed_action_flags = IGNORE_HELD_ITEM)) - if(!buckled) - return - buckled.user_unbuckle_mob(src,src) - else - if(src && buckled) - to_chat(src, span_warning("You fail to unbuckle yourself!")) - else - buckled.user_unbuckle_mob(src,src) + if(!HAS_TRAIT(src, TRAIT_RESTRAINED)) + buckled.user_unbuckle_mob(src, src) + return + + changeNext_move(CLICK_CD_BREAKOUT) + last_special = world.time + CLICK_CD_BREAKOUT + var/buckle_cd = 1 MINUTES + + if(handcuffed) + var/obj/item/restraints/cuffs = src.get_item_by_slot(ITEM_SLOT_HANDCUFFED) + buckle_cd = cuffs.breakouttime + + visible_message(span_warning("[src] attempts to unbuckle [p_them()]self!"), + span_notice("You attempt to unbuckle yourself... \ + (This will take around [DisplayTimeText(buckle_cd)] and you must stay still.)")) + + if(!do_after(src, buckle_cd, target = src, timed_action_flags = IGNORE_HELD_ITEM, hidden = TRUE)) + if(buckled) + to_chat(src, span_warning("You fail to unbuckle yourself!")) + return + + if(QDELETED(src) || isnull(buckled)) + return + + buckled.user_unbuckle_mob(src, src) + /mob/living/carbon/resist_fire() return !!apply_status_effect(/datum/status_effect/stop_drop_roll) @@ -282,34 +291,40 @@ cuff_resist(I) -/mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 1 MINUTES, cuff_break = 0) - if((cuff_break != INSTANT_CUFFBREAK) && (SEND_SIGNAL(src, COMSIG_MOB_REMOVING_CUFFS, I) & COMSIG_MOB_BLOCK_CUFF_REMOVAL)) +/** + * Helper to break the cuffs from hands + * @param {obj/item} cuffs - The cuffs to break + * @param {number} breakouttime - The time it takes to break the cuffs. Use SECONDS/MINUTES defines + * @param {number} cuff_break - Speed multiplier, 0 is default, see _DEFINES\combat.dm + */ +/mob/living/carbon/proc/cuff_resist(obj/item/cuffs, breakouttime = 1 MINUTES, cuff_break = 0) + if((cuff_break != INSTANT_CUFFBREAK) && (SEND_SIGNAL(src, COMSIG_MOB_REMOVING_CUFFS, cuffs) & COMSIG_MOB_BLOCK_CUFF_REMOVAL)) return //The blocking object should sent a fluff-appropriate to_chat about cuff removal being blocked - if(I.item_flags & BEING_REMOVED) - to_chat(src, span_warning("You're already attempting to remove [I]!")) + if(cuffs.item_flags & BEING_REMOVED) + to_chat(src, span_warning("You're already attempting to remove [cuffs]!")) return - I.item_flags |= BEING_REMOVED - breakouttime = I.breakouttime + cuffs.item_flags |= BEING_REMOVED + breakouttime = cuffs.breakouttime if(!cuff_break) - visible_message(span_warning("[src] attempts to remove [I]!")) - to_chat(src, span_notice("You attempt to remove [I]... (This will take around [DisplayTimeText(breakouttime)] and you need to stand still.)")) - if(do_after(src, breakouttime, target = src, timed_action_flags = IGNORE_HELD_ITEM)) - . = clear_cuffs(I, cuff_break) + visible_message(span_warning("[src] attempts to remove [cuffs]!")) + to_chat(src, span_notice("You attempt to remove [cuffs]... (This will take around [DisplayTimeText(breakouttime)] and you need to stand still.)")) + if(do_after(src, breakouttime, target = src, timed_action_flags = IGNORE_HELD_ITEM, hidden = TRUE)) + . = clear_cuffs(cuffs, cuff_break) else - to_chat(src, span_warning("You fail to remove [I]!")) + to_chat(src, span_warning("You fail to remove [cuffs]!")) else if(cuff_break == FAST_CUFFBREAK) - breakouttime = 50 - visible_message(span_warning("[src] is trying to break [I]!")) - to_chat(src, span_notice("You attempt to break [I]... (This will take around 5 seconds and you need to stand still.)")) + breakouttime = 5 SECONDS + visible_message(span_warning("[src] is trying to break [cuffs]!")) + to_chat(src, span_notice("You attempt to break [cuffs]... (This will take around 5 seconds and you need to stand still.)")) if(do_after(src, breakouttime, target = src, timed_action_flags = IGNORE_HELD_ITEM)) - . = clear_cuffs(I, cuff_break) + . = clear_cuffs(cuffs, cuff_break) else - to_chat(src, span_warning("You fail to break [I]!")) + to_chat(src, span_warning("You fail to break [cuffs]!")) else if(cuff_break == INSTANT_CUFFBREAK) - . = clear_cuffs(I, cuff_break) - I.item_flags &= ~BEING_REMOVED + . = clear_cuffs(cuffs, cuff_break) + cuffs.item_flags &= ~BEING_REMOVED /mob/living/carbon/proc/uncuff() if (handcuffed) @@ -410,6 +425,9 @@ if((HAS_TRAIT(src, TRAIT_NOHUNGER) || HAS_TRAIT(src, TRAIT_TOXINLOVER)) && !force) return TRUE + if(!force && HAS_TRAIT(src, TRAIT_STRONG_STOMACH)) + lost_nutrition *= 0.5 + SEND_SIGNAL(src, COMSIG_CARBON_VOMITED, distance, force) // cache some stuff that we'll need later (at least multiple times) @@ -426,7 +444,10 @@ span_userdanger("You try to throw up, but there's nothing in your stomach!"), ) if(stun) - Stun(20 SECONDS) + var/stun_time = 20 SECONDS + if(HAS_TRAIT(src, TRAIT_STRONG_STOMACH)) + stun_time *= 0.5 + Stun(stun_time) if(knockdown) Knockdown(20 SECONDS) return TRUE @@ -449,11 +470,14 @@ add_mood_event("vomit", /datum/mood_event/vomit) if(stun) - Stun(8 SECONDS) + var/stun_time = 8 SECONDS + if(!blood && HAS_TRAIT(src, TRAIT_STRONG_STOMACH)) + stun_time *= 0.5 + Stun(stun_time) if(knockdown) Knockdown(8 SECONDS) - playsound(get_turf(src), 'sound/effects/splat.ogg', 50, TRUE) + playsound(src, 'sound/effects/splat.ogg', 50, TRUE) var/need_mob_update = FALSE var/turf/location = get_turf(src) @@ -1161,9 +1185,7 @@ admin_ticket_log("[key_name_admin(usr)] has attempted to modify the bodyparts of [src]") if(href_list[VV_HK_MODIFY_ORGANS]) - if(!check_rights(NONE)) - return - usr.client.manipulate_organs(src) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/manipulate_organs, src) if(href_list[VV_HK_MARTIAL_ART]) if(!check_rights(NONE)) @@ -1485,3 +1507,13 @@ if (!IS_ORGANIC_LIMB(target_part) || (target_part.bodypart_flags & BODYPART_PSEUDOPART)) return FALSE return ..() + +/mob/living/carbon/ominous_nosebleed() + var/obj/item/bodypart/head = get_bodypart(BODY_ZONE_HEAD) + if(isnull(head)) + return ..() + if(HAS_TRAIT(src, TRAIT_NOBLOOD)) + to_chat(src, span_notice("You get a headache.")) + return + head.adjustBleedStacks(5) + visible_message(span_notice("[src] gets a nosebleed."), span_warning("You get a nosebleed.")) diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index f74c2c1ca21..41a958518c5 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -1,5 +1,5 @@ /mob/living/carbon/death(gibbed) - if(stat == DEAD || HAS_TRAIT(src, TRAIT_NODEATH) && !gibbed) + if(stat == DEAD) return losebreath = 0 diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index c534372d04c..154892d57ea 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -903,7 +903,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(!(I.slot_flags & slot)) var/excused = FALSE // Anything that's small or smaller can fit into a pocket by default - if((slot & (ITEM_SLOT_RPOCKET|ITEM_SLOT_LPOCKET)) && I.w_class <= WEIGHT_CLASS_SMALL) + if((slot & (ITEM_SLOT_RPOCKET|ITEM_SLOT_LPOCKET)) && I.w_class <= POCKET_WEIGHT_CLASS) excused = TRUE else if(slot & (ITEM_SLOT_SUITSTORE|ITEM_SLOT_BACKPACK|ITEM_SLOT_HANDS)) excused = TRUE diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index cf843c43b00..f63e692a118 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -20,7 +20,7 @@ GLOBAL_LIST_EMPTY(dead_players_during_shift) new /obj/effect/decal/remains/human(loc) /mob/living/carbon/human/death(gibbed) - if(stat == DEAD || HAS_TRAIT(src, TRAIT_NODEATH) && !gibbed) + if(stat == DEAD) return stop_sound_channel(CHANNEL_HEARTBEAT) var/obj/item/organ/internal/heart/human_heart = get_organ_slot(ORGAN_SLOT_HEART) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index ae67a379368..8786167e0dc 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -98,7 +98,7 @@ . += "[t_He] [t_has] [gloves.get_examine_string(user)] on [t_his] hands." else if(GET_ATOM_BLOOD_DNA_LENGTH(src)) if(num_hands) - . += span_warning("[t_He] [t_has] [num_hands > 1 ? "" : "a"] blood-stained hand[num_hands > 1 ? "s" : ""]!") + . += span_warning("[t_He] [t_has] [num_hands > 1 ? "" : "a "]blood-stained hand[num_hands > 1 ? "s" : ""]!") //handcuffed? if(handcuffed) diff --git a/code/modules/mob/living/carbon/human/human_stripping.dm b/code/modules/mob/living/carbon/human/human_stripping.dm index fadca82ab11..6dccf98e5d5 100644 --- a/code/modules/mob/living/carbon/human/human_stripping.dm +++ b/code/modules/mob/living/carbon/human/human_stripping.dm @@ -222,7 +222,7 @@ GLOBAL_LIST_INIT(strippable_human_items, create_strippable_list(list( source.log_message("is being pickpocketed of [item] by [key_name(user)] ([pocket_side])", LOG_VICTIM, color="orange", log_globally=FALSE) item.add_fingerprint(src) - var/result = start_unequip_mob(item, source, user, POCKET_STRIP_DELAY) + var/result = start_unequip_mob(item, source, user, strip_delay = POCKET_STRIP_DELAY, hidden = TRUE) if (!(result || HAS_TRAIT(user, TRAIT_STICKY_FINGERS))) //SKYRAT EDIT ADDITION original if (!result) warn_owner(source) diff --git a/code/modules/mob/living/carbon/human/init_signals.dm b/code/modules/mob/living/carbon/human/init_signals.dm index 6e16781a59e..dc5ce972105 100644 --- a/code/modules/mob/living/carbon/human/init_signals.dm +++ b/code/modules/mob/living/carbon/human/init_signals.dm @@ -8,6 +8,8 @@ RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_FAT), SIGNAL_REMOVETRAIT(TRAIT_FAT)), PROC_REF(on_fat)) RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_NOHUNGER), SIGNAL_REMOVETRAIT(TRAIT_NOHUNGER)), PROC_REF(on_nohunger)) + RegisterSignal(src, COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED, PROC_REF(check_pocket_weght)) + /// Gaining or losing [TRAIT_UNKNOWN] updates our name and our sechud /mob/living/carbon/human/proc/on_unknown_trait(datum/source) SIGNAL_HANDLER @@ -63,3 +65,19 @@ else hud_used?.hunger?.update_appearance() mob_mood?.update_nutrition_moodlets() + +/// Signal proc for [COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED] to check if an item is suddenly too heavy for our pockets +/mob/living/carbon/human/proc/check_pocket_weght(datum/source, obj/item/changed, old_w_class, new_w_class) + SIGNAL_HANDLER + if(changed != r_store && changed != l_store) + return + if(new_w_class <= POCKET_WEIGHT_CLASS) + return + if(!dropItemToGround(changed, force = TRUE)) + return + visible_message( + span_warning("[changed] falls out of [src]'s pockets!"), + span_warning("[changed] falls out of your pockets!"), + vision_distance = COMBAT_MESSAGE_RANGE, + ) + playsound(src, SFX_RUSTLE, 50, TRUE, -5, frequency = 0.8) 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 a1c3a245034..5a1c632acd7 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -731,10 +731,13 @@ to_chat(telepath, span_warning("You don't see anyone to send your thought to.")) return var/mob/living/recipient = tgui_input_list(telepath, "Choose a telepathic message recipient", "Telepathy", sort_names(recipient_options)) - if(isnull(recipient)) + if(isnull(recipient) || telepath.stat == DEAD || !is_species(telepath, /datum/species/jelly/stargazer)) return var/msg = tgui_input_text(telepath, title = "Telepathy") - if(isnull(msg)) + if(isnull(msg) || telepath.stat == DEAD || !is_species(telepath, /datum/species/jelly/stargazer)) + return + if(!(recipient in oview(telepath))) + to_chat(telepath, span_warning("You can't see [recipient] anymore!")) return if(recipient.can_block_magic(MAGIC_RESISTANCE_MIND, charge_cost = 0)) to_chat(telepath, span_warning("As you reach into [recipient]'s mind, you are stopped by a mental blockage. It seems you've been foiled.")) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 7923d0de7a4..99d1f5bc8ea 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -280,7 +280,8 @@ if(!can_breathe_vacuum && (o2_pp < safe_oxygen_min)) // Breathe insufficient amount of O2. oxygen_used = handle_suffocation(o2_pp, safe_oxygen_min, breath_gases[/datum/gas/oxygen][MOLES]) - throw_alert(ALERT_NOT_ENOUGH_OXYGEN, /atom/movable/screen/alert/not_enough_oxy) + if(!HAS_TRAIT(src, TRAIT_ANOSMIA)) + throw_alert(ALERT_NOT_ENOUGH_OXYGEN, /atom/movable/screen/alert/not_enough_oxy) else // Enough oxygen to breathe. failed_last_breath = FALSE @@ -307,7 +308,8 @@ if(!co2overloadtime) co2overloadtime = world.time else if((world.time - co2overloadtime) > 12 SECONDS) - throw_alert(ALERT_TOO_MUCH_CO2, /atom/movable/screen/alert/too_much_co2) + if(!HAS_TRAIT(src, TRAIT_ANOSMIA)) + throw_alert(ALERT_TOO_MUCH_CO2, /atom/movable/screen/alert/too_much_co2) Unconscious(6 SECONDS) // Lets hurt em a little, let them know we mean business. adjustOxyLoss(3) @@ -325,7 +327,8 @@ // Plasma side-effects. var/ratio = (breath_gases[/datum/gas/plasma][MOLES] / safe_plas_max) * 10 adjustToxLoss(clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE)) - throw_alert(ALERT_TOO_MUCH_PLASMA, /atom/movable/screen/alert/too_much_plas) + if(!HAS_TRAIT(src, TRAIT_ANOSMIA)) + throw_alert(ALERT_TOO_MUCH_PLASMA, /atom/movable/screen/alert/too_much_plas) else // Reset side-effects. clear_alert(ALERT_TOO_MUCH_PLASMA) @@ -356,6 +359,8 @@ miasma_disease.name = "Unknown" ForceContractDisease(miasma_disease, make_copy = TRUE, del_on_fail = TRUE) // Miasma side-effects. + if (HAS_TRAIT(src, TRAIT_ANOSMIA)) //We can't feel miasma without sense of smell + return switch(miasma_pp) if(0.25 to 5) // At lower pp, give out a little warning @@ -386,7 +391,8 @@ if(n2o_pp > n2o_para_min) // More N2O, more severe side-effects. Causes stun/sleep. n2o_euphoria = EUPHORIA_ACTIVE - throw_alert(ALERT_TOO_MUCH_N2O, /atom/movable/screen/alert/too_much_n2o) + if(!HAS_TRAIT(src, TRAIT_ANOSMIA)) + throw_alert(ALERT_TOO_MUCH_N2O, /atom/movable/screen/alert/too_much_n2o) // give them one second of grace to wake up and run away a bit! if(!HAS_TRAIT(src, TRAIT_SLEEPIMMUNE)) Unconscious(6 SECONDS) @@ -827,7 +833,7 @@ * Returns TRUE if heart status was changed (heart attack -> no heart attack, or visa versa) */ /mob/living/carbon/proc/set_heartattack(status) - if(!can_heartattack()) + if(status && !can_heartattack()) return FALSE var/obj/item/organ/internal/heart/heart = get_organ_slot(ORGAN_SLOT_HEART) diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index 0819c285d9a..51fb86d73ad 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -108,7 +108,6 @@ INVOKE_ASYNC(src, TYPE_PROC_REF(/mob, emote), "deathgasp") set_stat(DEAD) - unset_machine() timeofdeath = world.time station_timestamp_timeofdeath = station_time_timestamp() var/turf/death_turf = get_turf(src) diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index 64a2de72f43..412a63c00eb 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -656,20 +656,20 @@ to_chat(user, span_warning("\"[input]\"")) REPORT_CHAT_FILTER_TO_USER(user, filter_result) log_filter("IC Emote", input, filter_result) - SSblackbox.record_feedback("tally", "ic_blocked_words", 1, lowertext(config.ic_filter_regex.match)) + SSblackbox.record_feedback("tally", "ic_blocked_words", 1, LOWER_TEXT(config.ic_filter_regex.match)) return FALSE filter_result = is_soft_ic_filtered(input) if(filter_result) if(tgui_alert(user,"Your emote contains \"[filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to emote it?", "Soft Blocked Word", list("Yes", "No")) != "Yes") - SSblackbox.record_feedback("tally", "soft_ic_blocked_words", 1, lowertext(config.soft_ic_filter_regex.match)) + SSblackbox.record_feedback("tally", "soft_ic_blocked_words", 1, LOWER_TEXT(config.soft_ic_filter_regex.match)) log_filter("Soft IC Emote", input, filter_result) return FALSE message_admins("[ADMIN_LOOKUPFLW(user)] has passed the soft filter for emote \"[filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Emote: \"[input]\"") log_admin_private("[key_name(user)] has passed the soft filter for emote \"[filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Emote: \"[input]\"") - SSblackbox.record_feedback("tally", "passed_soft_ic_blocked_words", 1, lowertext(config.soft_ic_filter_regex.match)) + SSblackbox.record_feedback("tally", "passed_soft_ic_blocked_words", 1, LOWER_TEXT(config.soft_ic_filter_regex.match)) log_filter("Soft IC Emote (Passed)", input, filter_result) return TRUE diff --git a/code/modules/mob/living/inhand_holder.dm b/code/modules/mob/living/inhand_holder.dm index b4c9fbd34aa..808c8973963 100644 --- a/code/modules/mob/living/inhand_holder.dm +++ b/code/modules/mob/living/inhand_holder.dm @@ -20,7 +20,7 @@ righthand_file = rh_icon if(worn_slot_flags) slot_flags = worn_slot_flags - w_class = M.held_w_class + update_weight_class(M.held_w_class) deposit(M) . = ..() diff --git a/code/modules/mob/living/init_signals.dm b/code/modules/mob/living/init_signals.dm index ed496c0c84b..b8f1e60a612 100644 --- a/code/modules/mob/living/init_signals.dm +++ b/code/modules/mob/living/init_signals.dm @@ -157,7 +157,6 @@ /mob/living/proc/on_ui_blocked_trait_gain(datum/source) SIGNAL_HANDLER mobility_flags &= ~(MOBILITY_UI) - unset_machine() update_mob_action_buttons() /// Called when [TRAIT_UI_BLOCKED] is removed from the mob. diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 35866514b79..dd7e8a17c9b 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -66,9 +66,6 @@ handle_wounds(seconds_per_tick, times_fired) - if(machine) - machine.check_eye(src) - if(stat != DEAD) return 1 diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index b62aa1cde9d..d6c133ea3a8 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1407,9 +1407,14 @@ var/datum/dna/mob_DNA = has_dna() if(!mob_DNA || !mob_DNA.check_mutation(/datum/mutation/human/telekinesis) || !tkMaxRangeCheck(src, target)) - to_chat(src, span_warning("You are too far away!")) + if(!(action_bitflags & SILENT_ADJACENCY)) + to_chat(src, span_warning("You are too far away!")) return FALSE + if((action_bitflags & NEED_VENTCRAWL) && !HAS_TRAIT(src, TRAIT_VENTCRAWLER_NUDE) && !HAS_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS)) + to_chat(src, span_warning("You wouldn't fit!")) + return FALSE + if((action_bitflags & NEED_DEXTERITY) && !ISADVANCEDTOOLUSER(src)) to_chat(src, span_warning("You don't have the dexterity to do this!")) return FALSE @@ -1853,7 +1858,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) if(registered_z && old_level_new_clients == 0) for(var/datum/ai_controller/controller as anything in SSai_controllers.ai_controllers_by_zlevel[registered_z]) controller.set_ai_status(AI_STATUS_OFF) - + //Check the amount of clients exists on the Z level we're moving towards, excluding ourselves. var/new_level_old_clients = SSmobs.clients_by_zlevel[new_z].len @@ -2006,6 +2011,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) VV_DROPDOWN_OPTION(VV_HK_GIVE_HALLUCINATION, "Give Hallucination") VV_DROPDOWN_OPTION(VV_HK_GIVE_DELUSION_HALLUCINATION, "Give Delusion Hallucination") VV_DROPDOWN_OPTION(VV_HK_GIVE_GUARDIAN_SPIRIT, "Give Guardian Spirit") + VV_DROPDOWN_OPTION(VV_HK_ADMIN_RENAME, "Force Change Name") /mob/living/vv_do_topic(list/href_list) . = ..() @@ -2043,6 +2049,29 @@ GLOBAL_LIST_EMPTY(fire_appearances) return admin_give_guardian(usr) + if(href_list[VV_HK_ADMIN_RENAME]) + if(!check_rights(R_ADMIN)) + return + + var/old_name = real_name + var/new_name = sanitize_name(tgui_input_text(usr, "Enter the new name.", "Admin Rename", real_name)) + if(!new_name || new_name == real_name) + return + + fully_replace_character_name(real_name, new_name) + var/replace_preferences = !isnull(client) && (tgui_alert(usr, "Would you like to update the client's preference with the new name?", "Pref Overwrite", list("Yes", "No")) == "Yes") + if(replace_preferences) + client.prefs.write_preference(GLOB.preference_entries[/datum/preference/name/real_name], new_name) + + log_admin("forced rename", list( + "admin" = key_name(usr), + "player" = key_name(src), + "old_name" = old_name, + "new_name" = new_name, + "updated_prefs" = replace_preferences, + )) + message_admins("[key_name_admin(usr)] has forcibly changed the real name of [key_name(src)] from '[old_name]' to '[real_name]'[(replace_preferences ? " and their preferences" : "")]") + /mob/living/proc/move_to_error_room() var/obj/effect/landmark/error/error_landmark = locate(/obj/effect/landmark/error) in GLOB.landmarks_list if(error_landmark) @@ -2505,6 +2534,10 @@ GLOBAL_LIST_EMPTY(fire_appearances) apply_damage(rand(5,10), BRUTE, BODY_ZONE_CHEST) lattice.deconstruct(FALSE) +/// Prints an ominous message if something bad is going to happen to you +/mob/living/proc/ominous_nosebleed() + to_chat(src, span_warning("You feel a bit nauseous for just a moment.")) + /** * Proc used by different station pets such as Ian and Poly so that some of their data can persist between rounds. * This base definition only contains a trait and comsig to stop memory from being (over)written. diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm index a364c5691de..16705e90165 100644 --- a/code/modules/mob/living/living_say.dm +++ b/code/modules/mob/living/living_say.dm @@ -127,11 +127,11 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( return if(message_mods[RADIO_EXTENSION] == MODE_ADMIN) - client?.cmd_admin_say(message) + SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/cmd_admin_say, message) return if(message_mods[RADIO_EXTENSION] == MODE_DEADMIN) - client?.dsay(message) + SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/dsay, message) return // dead is the only state you can never emote diff --git a/code/modules/mob/living/silicon/ai/_preferences.dm b/code/modules/mob/living/silicon/ai/_preferences.dm index 4b0aaaecc25..10958b2adc4 100644 --- a/code/modules/mob/living/silicon/ai/_preferences.dm +++ b/code/modules/mob/living/silicon/ai/_preferences.dm @@ -115,7 +115,7 @@ GLOBAL_LIST_INIT(ai_core_display_screens, sort_list(list( else if(input == "Random") input = pick(GLOB.ai_core_display_screens - "Random") - return "ai-[lowertext(input)]" + return "ai-[LOWER_TEXT(input)]" /proc/resolve_ai_icon(input) if (input == "Portrait") diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 5f7571186be..292b0f1d7c1 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -1,17 +1,5 @@ #define CALL_BOT_COOLDOWN 900 -//Not sure why this is necessary... -/proc/AutoUpdateAI(obj/subject) - var/is_in_use = 0 - if (subject != null) - for(var/A in GLOB.ai_list) - var/mob/living/silicon/ai/M = A - if ((M.client && M.machine == subject)) - is_in_use = 1 - subject.attack_ai(M) - return is_in_use - - /mob/living/silicon/ai name = "AI" real_name = "AI" @@ -645,7 +633,6 @@ /mob/living/silicon/ai/proc/ai_network_change() set category = "AI Commands" set name = "Jump To Network" - unset_machine() ai_tracking_tool.reset_tracking() var/cameralist[0] diff --git a/code/modules/mob/living/silicon/ai/ai_say.dm b/code/modules/mob/living/silicon/ai/ai_say.dm index d655ce03a33..2a8b8e6c4a0 100644 --- a/code/modules/mob/living/silicon/ai/ai_say.dm +++ b/code/modules/mob/living/silicon/ai/ai_say.dm @@ -126,7 +126,7 @@ words.len = 30 for(var/word in words) - word = lowertext(trim(word)) + word = LOWER_TEXT(trim(word)) if(!word) words -= word continue @@ -156,7 +156,7 @@ /proc/play_vox_word(word, ai_turf, mob/only_listener) - word = lowertext(word) + word = LOWER_TEXT(word) if(GLOB.vox_sounds[word]) diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index e8c1919b020..98a2e629776 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -202,7 +202,6 @@ current = null if(ai_tracking_tool) ai_tracking_tool.reset_tracking() - unset_machine() if(isturf(loc) && (QDELETED(eyeobj) || !eyeobj.loc)) to_chat(src, "ERROR: Eyeobj not found. Creating new eye...") diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 76f5c2eec93..b11f125d38c 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -12,9 +12,6 @@ if(isturf(loc) && (QDELETED(eyeobj) || !eyeobj.loc)) view_core() - if(machine) - machine.check_eye(src) - // Handle power damage (oxy) if(aiRestorePowerRoutine) // Lost power diff --git a/code/modules/mob/living/silicon/robot/robot_model.dm b/code/modules/mob/living/silicon/robot/robot_model.dm index 2f4f2d70f26..44207ee8948 100644 --- a/code/modules/mob/living/silicon/robot/robot_model.dm +++ b/code/modules/mob/living/silicon/robot/robot_model.dm @@ -393,7 +393,7 @@ /obj/item/analyzer, /obj/item/holosign_creator/atmos, // Skyrat Edit - Adds Holofans to engineering borgos /obj/item/assembly/signaler/cyborg, - /obj/item/areaeditor/blueprints/cyborg, + /obj/item/blueprints/cyborg, /obj/item/electroadaptive_pseudocircuit, /obj/item/stack/sheet/iron, /obj/item/stack/sheet/glass, diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 27bbec88292..ec204dbc82b 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -29,6 +29,7 @@ light_power = 0.6 del_on_death = TRUE req_one_access = list(ACCESS_ROBOTICS) + interaction_flags_click = ALLOW_SILICON_REACH ///Cooldown between salutations for commissioned bots COOLDOWN_DECLARE(next_salute_check) @@ -411,13 +412,9 @@ ui = new(user, src, "SimpleBot", name) ui.open() -/mob/living/simple_animal/bot/AltClick(mob/user) - . = ..() - if(!can_interact(user)) - return - if(!user.can_perform_action(src, ALLOW_SILICON_REACH)) - return +/mob/living/simple_animal/bot/click_alt(mob/user) unlock_with_id(user) + return CLICK_ACTION_SUCCESS /mob/living/simple_animal/bot/proc/unlock_with_id(mob/user) if(bot_cover_flags & BOT_COVER_EMAGGED) diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm index faa7d3a9edb..ae1c52d1652 100644 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm @@ -140,7 +140,7 @@ return data // Actions received from TGUI -/mob/living/simple_animal/bot/floorbot/ui_act(action, params) +/mob/living/simple_animal/bot/floorbot/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() if(. || (bot_cover_flags & BOT_COVER_LOCKED && !HAS_SILICON_ACCESS(usr))) return @@ -161,7 +161,7 @@ tilestack.forceMove(drop_location()) if("line_mode") var/setdir = tgui_input_list(usr, "Select construction direction", "Direction", list("north", "east", "south", "west", "disable")) - if(isnull(setdir)) + if(isnull(setdir) || QDELETED(ui) || ui.status != UI_INTERACTIVE) return switch(setdir) if("north") diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm index b8ceb33a37d..cf937e42bb7 100644 --- a/code/modules/mob/logout.dm +++ b/code/modules/mob/logout.dm @@ -2,7 +2,6 @@ SEND_SIGNAL(src, COMSIG_MOB_LOGOUT) log_message("[key_name(src)] is no longer owning mob [src]([src.type])", LOG_OWNERSHIP) SStgui.on_logout(src) - unset_machine() remove_from_player_list() ..() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 30d0a528b96..1142fff130b 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -30,7 +30,6 @@ else if(ckey) stack_trace("Mob without client but with associated ckey, [ckey], has been deleted.") - unset_machine() remove_from_mob_list() remove_from_dead_mob_list() remove_from_alive_mob_list() @@ -902,7 +901,6 @@ set name = "Cancel Camera View" set category = "OOC" reset_perspective(null) - unset_machine() //suppress the .click/dblclick macros so people can't use them to identify the location of items or aimbot /mob/verb/DisClick(argu = null as anything, sec = "" as text, number1 = 0 as num , number2 = 0 as num) @@ -1014,7 +1012,7 @@ selected_hand = (active_hand_index % held_items.len)+1 if(istext(selected_hand)) - selected_hand = lowertext(selected_hand) + selected_hand = LOWER_TEXT(selected_hand) if(selected_hand == "right" || selected_hand == "r") selected_hand = 2 if(selected_hand == "left" || selected_hand == "l") @@ -1199,6 +1197,10 @@ * * FORBID_TELEKINESIS_REACH - If telekinesis is forbidden to perform action from a distance (ex. canisters are blacklisted from telekinesis manipulation) * * ALLOW_SILICON_REACH - If silicons are allowed to perform action from a distance (silicons can operate airlocks from far away) * * ALLOW_RESTING - If resting on the floor is allowed to perform action () + * * ALLOW_VENTCRAWL - Mobs with ventcrawl traits can alt-click this to vent + * + * silence_adjacency: Sometimes we want to use this proc to check interaction without allowing it to throw errors for base case adjacency + * Alt click uses this, as otherwise you can detect what is interactable from a distance via the error message **/ /mob/proc/can_perform_action(atom/movable/target, action_bitflags) return @@ -1477,9 +1479,7 @@ regenerate_icons() if(href_list[VV_HK_PLAYER_PANEL]) - if(!check_rights(NONE)) - return - usr.client.holder.show_player_panel(src) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/show_player_panel, src) if(href_list[VV_HK_GODMODE]) if(!check_rights(R_ADMIN)) @@ -1487,34 +1487,22 @@ usr.client.cmd_admin_godmode(src) if(href_list[VV_HK_GIVE_MOB_ACTION]) - if(!check_rights(NONE)) - return - usr.client.give_mob_action(src) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/give_mob_action, src) if(href_list[VV_HK_REMOVE_MOB_ACTION]) - if(!check_rights(NONE)) - return - usr.client.remove_mob_action(src) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/remove_mob_action, src) if(href_list[VV_HK_GIVE_SPELL]) - if(!check_rights(NONE)) - return - usr.client.give_spell(src) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/give_spell, src) if(href_list[VV_HK_REMOVE_SPELL]) - if(!check_rights(NONE)) - return - usr.client.remove_spell(src) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/remove_spell, src) if(href_list[VV_HK_GIVE_DISEASE]) - if(!check_rights(NONE)) - return - usr.client.give_disease(src) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/give_disease, src) if(href_list[VV_HK_GIB]) - if(!check_rights(R_FUN)) - return - usr.client.cmd_admin_gib(src) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/gib_them, src) if(href_list[VV_HK_BUILDMODE]) if(!check_rights(R_BUILD)) @@ -1522,19 +1510,13 @@ togglebuildmode(src) if(href_list[VV_HK_DROP_ALL]) - if(!check_rights(NONE)) - return - usr.client.cmd_admin_drop_everything(src) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/drop_everything, src) if(href_list[VV_HK_DIRECT_CONTROL]) - if(!check_rights(NONE)) - return - usr.client.cmd_assume_direct_control(src) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/cmd_assume_direct_control, src) if(href_list[VV_HK_GIVE_DIRECT_CONTROL]) - if(!check_rights(NONE)) - return - usr.client.cmd_give_direct_control(src) + return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/cmd_give_direct_control, src) if(href_list[VV_HK_OFFER_GHOSTS]) if(!check_rights(NONE)) @@ -1641,9 +1623,6 @@ /mob/vv_edit_var(var_name, var_value) switch(var_name) - if(NAMEOF(src, machine)) - set_machine(var_value) - . = TRUE if(NAMEOF(src, focus)) set_focus(var_value) . = TRUE diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 44d0db90355..2a5be377ecd 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -79,9 +79,6 @@ var/computer_id = null var/list/logging = list() - /// The machine the mob is interacting with (this is very bad old code btw) - var/obj/machinery/machine = null - /// Tick time the mob can next move var/next_move = null diff --git a/code/modules/mob/mob_say.dm b/code/modules/mob/mob_say.dm index 8f1398ce244..f634bd187a4 100644 --- a/code/modules/mob/mob_say.dm +++ b/code/modules/mob/mob_say.dm @@ -66,17 +66,17 @@ to_chat(src, span_warning("\"[message]\"")) REPORT_CHAT_FILTER_TO_USER(src, filter_result) log_filter("IC", message, filter_result) - SSblackbox.record_feedback("tally", "ic_blocked_words", 1, lowertext(config.ic_filter_regex.match)) + SSblackbox.record_feedback("tally", "ic_blocked_words", 1, LOWER_TEXT(config.ic_filter_regex.match)) return FALSE if(soft_filter_result && !filterproof) if(tgui_alert(usr,"Your message contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to say it?", "Soft Blocked Word", list("Yes", "No")) != "Yes") - SSblackbox.record_feedback("tally", "soft_ic_blocked_words", 1, lowertext(config.soft_ic_filter_regex.match)) + SSblackbox.record_feedback("tally", "soft_ic_blocked_words", 1, LOWER_TEXT(config.soft_ic_filter_regex.match)) log_filter("Soft IC", message, filter_result) return FALSE message_admins("[ADMIN_LOOKUPFLW(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Message: \"[message]\"") log_admin_private("[key_name(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term. Message: \"[message]\"") - SSblackbox.record_feedback("tally", "passed_soft_ic_blocked_words", 1, lowertext(config.soft_ic_filter_regex.match)) + SSblackbox.record_feedback("tally", "passed_soft_ic_blocked_words", 1, LOWER_TEXT(config.soft_ic_filter_regex.match)) log_filter("Soft IC (Passed)", message, filter_result) if(client && !(ignore_spam || forced)) @@ -223,7 +223,7 @@ if(stat == CONSCIOUS) //necessary indentation so it gets stripped of the semicolon anyway. mods[MODE_HEADSET] = TRUE else if((key in GLOB.department_radio_prefixes) && length(message) > length(key) + 1 && !mods[RADIO_EXTENSION]) - mods[RADIO_KEY] = lowertext(message[1 + length(key)]) + mods[RADIO_KEY] = LOWER_TEXT(message[1 + length(key)]) mods[RADIO_EXTENSION] = GLOB.department_radio_keys[mods[RADIO_KEY]] chop_to = length(key) + 2 else if(key == "," && !mods[LANGUAGE_EXTENSION]) diff --git a/code/modules/mod/mod_link.dm b/code/modules/mod/mod_link.dm index 634b1dd648f..c3d5040c815 100644 --- a/code/modules/mod/mod_link.dm +++ b/code/modules/mod/mod_link.dm @@ -191,6 +191,8 @@ /obj/item/clothing/neck/link_scryer/attack_self(mob/user, modifiers) var/new_label = reject_bad_text(tgui_input_text(user, "Change the visible name", "Set Name", label, MAX_NAME_LEN)) + if(!user.is_holding(src)) + return if(!new_label) balloon_alert(user, "invalid name!") return diff --git a/code/modules/mod/mod_theme.dm b/code/modules/mod/mod_theme.dm index 88f697ccd48..a408be23b1f 100644 --- a/code/modules/mod/mod_theme.dm +++ b/code/modules/mod/mod_theme.dm @@ -891,6 +891,7 @@ /obj/item/grown/bananapeel, /obj/item/reagent_containers/spray/waterflower, /obj/item/instrument, + /obj/item/toy/balloon_animal, ) skins = list( "cosmohonk" = list( diff --git a/code/modules/mod/mod_types.dm b/code/modules/mod/mod_types.dm index 47f588eb80b..f0bca6b0980 100644 --- a/code/modules/mod/mod_types.dm +++ b/code/modules/mod/mod_types.dm @@ -212,6 +212,7 @@ /obj/item/mod/module/storage, /obj/item/mod/module/waddle, /obj/item/mod/module/bikehorn, + /obj/item/mod/module/balloon_advanced, ) /obj/item/mod/control/pre_equipped/traitor diff --git a/code/modules/mod/modules/modules_antag.dm b/code/modules/mod/modules/modules_antag.dm index 2462f62a3d3..bd96c5aec5f 100644 --- a/code/modules/mod/modules/modules_antag.dm +++ b/code/modules/mod/modules/modules_antag.dm @@ -460,10 +460,10 @@ /obj/item/mod/module/plate_compression/on_install() old_size = mod.w_class - mod.w_class = new_size + mod.update_weight_class(new_size) /obj/item/mod/module/plate_compression/on_uninstall(deleting = FALSE) - mod.w_class = old_size + mod.update_weight_class(old_size) old_size = null if(!mod.loc) return diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index f80fd952cef..2aec3e361c4 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -506,9 +506,16 @@ if(!drain_power(use_energy_cost * levels)) return NONE new /obj/effect/temp_visual/mook_dust(fell_on) - mod.wearer.Stun(levels * 1 SECONDS) + + /// Boolean that tracks whether we fell more than one z-level. If TRUE, we stagger our wearer. + var/extreme_fall = FALSE + + if(levels >= 2) + extreme_fall = TRUE + mod.wearer.adjust_staggered_up_to(STAGGERED_SLOWDOWN_LENGTH * levels, 10 SECONDS) + mod.wearer.visible_message( - span_notice("[mod.wearer] lands on [fell_on] safely."), + span_notice("[mod.wearer] lands on [fell_on] safely[extreme_fall ? ", but barely manages to stay on [p_their()] feet." : ", and quite stylishly on [p_their()] feet" ]."), span_notice("[src] protects you from the damage!"), ) return ZIMPACT_CANCEL_DAMAGE|ZIMPACT_NO_MESSAGE|ZIMPACT_NO_SPIN diff --git a/code/modules/mod/modules/modules_service.dm b/code/modules/mod/modules/modules_service.dm index b4870a84ec5..be71c621802 100644 --- a/code/modules/mod/modules/modules_service.dm +++ b/code/modules/mod/modules/modules_service.dm @@ -19,6 +19,31 @@ playsound(src, 'sound/items/bikehorn.ogg', 100, FALSE) drain_power(use_energy_cost) +///Advanced Balloon Blower - Blows a long balloon. +/obj/item/mod/module/balloon_advanced + name = "MOD advanced balloon blower module" + desc = "A relatively new piece of technology developed by finest clown engineers to make long balloons and balloon animals \ + at party-appropriate rate." + icon_state = "bloon" + module_type = MODULE_USABLE + complexity = 1 + use_energy_cost = DEFAULT_CHARGE_DRAIN * 0.5 + incompatible_modules = list(/obj/item/mod/module/balloon_advanced) + cooldown_time = 15 SECONDS + +/obj/item/mod/module/balloon_advanced/on_use() + . = ..() + if(!.) + return + if(!do_after(mod.wearer, 15 SECONDS, target = mod)) + return FALSE + mod.wearer.adjustOxyLoss(20) + playsound(src, 'sound/items/modsuit/inflate_bloon.ogg', 50, TRUE) + var/obj/item/toy/balloon/long/l_balloon = new(get_turf(src)) + mod.wearer.put_in_hands(l_balloon) + drain_power(use_energy_cost) + + ///Microwave Beam - Microwaves items instantly. /obj/item/mod/module/microwave_beam name = "MOD microwave beam module" diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index c63441124ae..c7369724ee4 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -223,19 +223,18 @@ /obj/item/modular_computer/get_cell() return internal_cell -/obj/item/modular_computer/AltClick(mob/user) - . = ..() +/obj/item/modular_computer/click_alt(mob/user) if(issilicon(user)) - return FALSE - if(!user.can_perform_action(src)) - return FALSE + return NONE if(RemoveID(user)) - return TRUE + return CLICK_ACTION_SUCCESS if(istype(inserted_pai)) // Remove pAI remove_pai(user) - return TRUE + return CLICK_ACTION_SUCCESS + + return CLICK_ACTION_BLOCKING // Gets IDs/access levels from card slot. Would be useful when/if PDAs would become modular PCs. //guess what /obj/item/modular_computer/GetAccess() diff --git a/code/modules/modular_computers/computers/item/laptop.dm b/code/modules/modular_computers/computers/item/laptop.dm index d3b620cdfc9..b55fb6d2ee6 100644 --- a/code/modules/modular_computers/computers/item/laptop.dm +++ b/code/modules/modular_computers/computers/item/laptop.dm @@ -91,25 +91,22 @@ toggle_open(user) -/obj/item/modular_computer/laptop/AltClick(mob/user) - . = ..() - if(!can_interact(user)) - return - if(screen_on) // Close it. - try_toggle_open(user) - else - return ..() +/obj/item/modular_computer/laptop/click_alt(mob/user) + if(!screen_on) + return CLICK_ACTION_BLOCKING + try_toggle_open(user) // Close it. + return CLICK_ACTION_SUCCESS /obj/item/modular_computer/laptop/proc/toggle_open(mob/living/user=null) if(screen_on) to_chat(user, span_notice("You close \the [src].")) slowdown = initial(slowdown) - w_class = initial(w_class) + update_weight_class(initial(w_class)) drag_slowdown = initial(drag_slowdown) else to_chat(user, span_notice("You open \the [src].")) slowdown = slowdown_open - w_class = w_class_open + update_weight_class(w_class_open) drag_slowdown = slowdown_open if(isliving(loc)) var/mob/living/localmob = loc diff --git a/code/modules/modular_computers/computers/item/pda.dm b/code/modules/modular_computers/computers/item/pda.dm index 37ef56a0626..b6efa629d5e 100644 --- a/code/modules/modular_computers/computers/item/pda.dm +++ b/code/modules/modular_computers/computers/item/pda.dm @@ -161,12 +161,6 @@ inserted_item = attacking_item playsound(src, 'sound/machines/pda_button1.ogg', 50, TRUE) -/obj/item/modular_computer/pda/AltClick(mob/user) - . = ..() - if(.) - return - - remove_pen(user) /obj/item/modular_computer/pda/CtrlClick(mob/user) . = ..() diff --git a/code/modules/modular_computers/computers/machinery/console_presets.dm b/code/modules/modular_computers/computers/machinery/console_presets.dm index 18f394d6ee0..0ec80da4bbb 100644 --- a/code/modules/modular_computers/computers/machinery/console_presets.dm +++ b/code/modules/modular_computers/computers/machinery/console_presets.dm @@ -94,7 +94,7 @@ setup_starting_software() REGISTER_REQUIRED_MAP_ITEM(1, 1) if(department_type) - name = "[lowertext(initial(department_type.department_name))] [name]" + name = "[LOWER_TEXT(initial(department_type.department_name))] [name]" cpu.name = name /obj/machinery/modular_computer/preset/cargochat/proc/add_starting_software() @@ -105,7 +105,7 @@ return var/datum/computer_file/program/chatclient/chatprogram = cpu.find_file_by_name("ntnrc_client") - chatprogram.username = "[lowertext(initial(department_type.department_name))]_department" + chatprogram.username = "[LOWER_TEXT(initial(department_type.department_name))]_department" cpu.idle_threads += chatprogram var/datum/computer_file/program/department_order/orderprogram = cpu.find_file_by_name("dept_order") @@ -144,7 +144,7 @@ update_appearance(UPDATE_ICON) // Rest of the chat program setup is done in LateInit -/obj/machinery/modular_computer/preset/cargochat/cargo/LateInitialize() +/obj/machinery/modular_computer/preset/cargochat/cargo/post_machine_initialize() . = ..() var/datum/computer_file/program/chatclient/chatprogram = cpu.find_file_by_name("ntnrc_client") chatprogram.username = "cargo_requests_operator" diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm index 0e17f012453..6f0050534cc 100644 --- a/code/modules/modular_computers/computers/machinery/modular_computer.dm +++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm @@ -116,11 +116,11 @@ SIGNAL_HANDLER return update_icon(updates) -/obj/machinery/modular_computer/AltClick(mob/user) - . = ..() +/obj/machinery/modular_computer/click_alt(mob/user) if(CPU_INTERACTABLE(user) || !can_interact(user)) - return - cpu.AltClick(user) + return NONE + cpu.click_alt(user) + return CLICK_ACTION_SUCCESS //ATTACK HAND IGNORING PARENT RETURN VALUE // On-click handling. Turns on the computer if it's off and opens the GUI. diff --git a/code/modules/modular_computers/file_system/programs/atmosscan.dm b/code/modules/modular_computers/file_system/programs/atmosscan.dm index 8f29af43510..7e260872859 100644 --- a/code/modules/modular_computers/file_system/programs/atmosscan.dm +++ b/code/modules/modular_computers/file_system/programs/atmosscan.dm @@ -44,7 +44,7 @@ var/list/airs = islist(mixture) ? mixture : list(mixture) var/list/new_gasmix_data = list() for(var/datum/gas_mixture/air as anything in airs) - var/mix_name = capitalize(lowertext(target.name)) + var/mix_name = capitalize(LOWER_TEXT(target.name)) if(airs.len != 1) //not a unary gas mixture mix_name += " - Node [airs.Find(air)]" new_gasmix_data += list(gas_mixture_parser(air, mix_name)) diff --git a/code/modules/modular_computers/file_system/programs/secureye.dm b/code/modules/modular_computers/file_system/programs/secureye.dm index eee170e7c2c..aa3ed0e5828 100644 --- a/code/modules/modular_computers/file_system/programs/secureye.dm +++ b/code/modules/modular_computers/file_system/programs/secureye.dm @@ -70,7 +70,7 @@ // Convert networks to lowercase for(var/i in network) network -= i - network += lowertext(i) + network += LOWER_TEXT(i) // Initialize map objects cam_screen = new cam_screen.generate_view(map_name) diff --git a/code/modules/pai/door_jack.dm b/code/modules/pai/door_jack.dm index 182cdc10027..36220ecface 100644 --- a/code/modules/pai/door_jack.dm +++ b/code/modules/pai/door_jack.dm @@ -104,17 +104,17 @@ /mob/living/silicon/pai/proc/hack_door() if(!hacking_cable) return FALSE - if(!hacking_cable.machine) + if(!hacking_cable.hacking_machine) balloon_alert(src, "nothing connected") return FALSE playsound(src, 'sound/machines/airlock_alien_prying.ogg', 50, TRUE) balloon_alert(src, "overriding...") // Now begin hacking - if(!do_after(src, 15 SECONDS, hacking_cable.machine, timed_action_flags = NONE, progress = TRUE)) + if(!do_after(src, 15 SECONDS, hacking_cable.hacking_machine, timed_action_flags = NONE, progress = TRUE)) balloon_alert(src, "failed! retracting...") QDEL_NULL(hacking_cable) return FALSE - var/obj/machinery/door/door = hacking_cable.machine + var/obj/machinery/door/door = hacking_cable.hacking_machine balloon_alert(src, "success") door.open() QDEL_NULL(hacking_cable) diff --git a/code/modules/paperwork/carbonpaper.dm b/code/modules/paperwork/carbonpaper.dm index 1dfe4ea7821..9c8ec0b8640 100644 --- a/code/modules/paperwork/carbonpaper.dm +++ b/code/modules/paperwork/carbonpaper.dm @@ -20,11 +20,11 @@ return . += span_notice("Right-click to tear off the carbon-copy (you must use both hands).") -/obj/item/paper/carbon/AltClick(mob/living/user) +/obj/item/paper/carbon/click_alt(mob/living/user) if(!copied) to_chat(user, span_notice("Take off the carbon copy first.")) - return - return ..() + return CLICK_ACTION_BLOCKING + return CLICK_ACTION_SUCCESS /obj/item/paper/carbon/proc/removecopy(mob/living/user) if(copied) diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm index 7285aa3172d..8b475ed6324 100644 --- a/code/modules/paperwork/clipboard.dm +++ b/code/modules/paperwork/clipboard.dm @@ -71,13 +71,16 @@ pen = null update_icon() -/obj/item/clipboard/AltClick(mob/user) - ..() - if(pen) - if(integrated_pen) - to_chat(user, span_warning("You can't seem to find a way to remove [src]'s [pen].")) - else - remove_pen(user) +/obj/item/clipboard/click_alt(mob/user) + if(isnull(pen)) + return CLICK_ACTION_BLOCKING + + if(integrated_pen) + to_chat(user, span_warning("You can't seem to find a way to remove [src]'s [pen].")) + return CLICK_ACTION_BLOCKING + + remove_pen(user) + return CLICK_ACTION_SUCCESS /obj/item/clipboard/update_overlays() . = ..() diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm index e4ac04a22b6..d89d74d7f8e 100644 --- a/code/modules/paperwork/handlabeler.dm +++ b/code/modules/paperwork/handlabeler.dm @@ -107,12 +107,9 @@ to_chat(user, span_notice("You turn off [src].")) return TRUE -/obj/item/hand_labeler/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) - . = ..() - if(. & ITEM_INTERACT_ANY_BLOCKER) - return . +/obj/item/hand_labeler/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(!istype(tool, /obj/item/hand_labeler_refill)) - return . + return NONE balloon_alert(user, "refilled") qdel(tool) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 5aac6d93bc3..e1bddd6feff 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -30,6 +30,7 @@ grind_results = list(/datum/reagent/cellulose = 3) color = COLOR_WHITE item_flags = SKIP_FANTASY_ON_SPAWN + interaction_flags_click = NEED_DEXTERITY|NEED_HANDS /// Lazylist of raw, unsanitised, unparsed text inputs that have been made to the paper. var/list/datum/paper_input/raw_text_inputs @@ -359,13 +360,13 @@ return TRUE return ..() -/obj/item/paper/AltClick(mob/living/user) - . = ..() - if(!user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS)) - return +/obj/item/paper/click_alt(mob/living/user) if(HAS_TRAIT(user, TRAIT_PAPER_MASTER)) - return make_plane(user, /obj/item/paperplane/syndicate) - return make_plane(user, /obj/item/paperplane) + make_plane(user, /obj/item/paperplane/syndicate) + return CLICK_ACTION_SUCCESS + make_plane(user, /obj/item/paperplane) + return CLICK_ACTION_SUCCESS + /** @@ -374,9 +375,9 @@ * * Arguments: * * mob/living/user - who's folding - * * obj/item/paperplane/plane_type - what it will be folded into (path) + * * plane_type - what it will be folded into (path) */ -/obj/item/paper/proc/make_plane(mob/living/user, obj/item/paperplane/plane_type = /obj/item/paperplane) +/obj/item/paper/proc/make_plane(mob/living/user, plane_type = /obj/item/paperplane) balloon_alert(user, "folded into a plane") user.temporarilyRemoveItemFromInventory(src) var/obj/item/paperplane/new_plane = new plane_type(loc, src) diff --git a/code/modules/paperwork/paper_cutter.dm b/code/modules/paperwork/paper_cutter.dm index ae93a1daad8..8e4fedf2fda 100644 --- a/code/modules/paperwork/paper_cutter.dm +++ b/code/modules/paperwork/paper_cutter.dm @@ -141,16 +141,14 @@ return ..() -/obj/item/papercutter/AltClick(mob/user) - if(!user.Adjacent(src)) - return ..() - +/obj/item/papercutter/click_alt(mob/user) // can only remove one at a time; paper goes first, as its most likely what players will want to be taking out if(!isnull(stored_paper)) user.put_in_hands(stored_paper) else if(!isnull(stored_blade) && !blade_secured) user.put_in_hands(stored_blade) update_appearance() + return CLICK_ACTION_SUCCESS /obj/item/papercutter/attack_hand_secondary(mob/user, list/modifiers) if(!stored_blade) diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 2a9e78e2489..ec71eda2e46 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -44,6 +44,7 @@ dart_insert_projectile_icon_state, \ CALLBACK(src, PROC_REF(get_dart_var_modifiers))\ ) + AddElement(/datum/element/tool_renaming) RegisterSignal(src, COMSIG_DART_INSERT_ADDED, PROC_REF(on_inserted_into_dart)) RegisterSignal(src, COMSIG_DART_INSERT_REMOVED, PROC_REF(on_removed_from_dart)) @@ -179,6 +180,7 @@ if(current_skin) desc = "It's an expensive [current_skin] fountain pen. The nib is quite sharp." + /obj/item/pen/fountain/captain/proc/reskin_dart_insert(datum/component/dart_insert/insert_comp) if(!istype(insert_comp)) //You really shouldn't be sending this signal from anything other than a dart_insert component return @@ -209,54 +211,6 @@ log_combat(user, M, "stabbed", src) return TRUE -/obj/item/pen/afterattack(obj/O, mob/living/user, proximity) - . = ..() - - if (!proximity) - return . - - . |= AFTERATTACK_PROCESSED_ITEM - - //Changing name/description of items. Only works if they have the UNIQUE_RENAME object flag set - if(isobj(O) && (O.obj_flags & UNIQUE_RENAME)) - var/penchoice = tgui_input_list(user, "What would you like to edit?", "Pen Setting", list("Rename", "Description", "Reset")) - if(QDELETED(O) || !user.can_perform_action(O)) - return - if(penchoice == "Rename") - var/input = tgui_input_text(user, "What do you want to name [O]?", "Object Name", "[O.name]", MAX_NAME_LEN) - var/oldname = O.name - if(QDELETED(O) || !user.can_perform_action(O)) - return - if(input == oldname || !input) - to_chat(user, span_notice("You changed [O] to... well... [O].")) - else - O.AddComponent(/datum/component/rename, input, O.desc) - to_chat(user, span_notice("You have successfully renamed \the [oldname] to [O].")) - ADD_TRAIT(O, TRAIT_WAS_RENAMED, PEN_LABEL_TRAIT) - O.update_appearance(UPDATE_ICON) - - if(penchoice == "Description") - var/input = tgui_input_text(user, "Describe [O]", "Description", "[O.desc]", 280) - var/olddesc = O.desc - if(QDELETED(O) || !user.can_perform_action(O)) - return - if(input == olddesc || !input) - to_chat(user, span_notice("You decide against changing [O]'s description.")) - else - O.AddComponent(/datum/component/rename, O.name, input) - to_chat(user, span_notice("You have successfully changed [O]'s description.")) - ADD_TRAIT(O, TRAIT_WAS_RENAMED, PEN_LABEL_TRAIT) - O.update_appearance(UPDATE_ICON) - - if(penchoice == "Reset") - if(QDELETED(O) || !user.can_perform_action(O)) - return - - qdel(O.GetComponent(/datum/component/rename)) - to_chat(user, span_notice("You have successfully reset [O]'s name and description.")) - REMOVE_TRAIT(O, TRAIT_WAS_RENAMED, PEN_LABEL_TRAIT) - O.update_appearance(UPDATE_ICON) - /obj/item/pen/get_writing_implement_details() return list( interaction_mode = MODE_WRITING, diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 207b8351a58..0712e516de4 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -547,7 +547,7 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks()) toner_cartridge = object balloon_alert(user, "cartridge inserted") - else if(istype(object, /obj/item/areaeditor/blueprints)) + else if(istype(object, /obj/item/blueprints)) to_chat(user, span_warning("\The [object] is too large to put into the copier. You need to find something else to record the document.")) else if(istype(object, /obj/item/paperwork)) diff --git a/code/modules/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm index 0d5f37cb867..35462a24d86 100644 --- a/code/modules/photography/camera/camera.dm +++ b/code/modules/photography/camera/camera.dm @@ -72,10 +72,9 @@ picture_size_y = min(clamp(desired_y, picture_size_y_min, picture_size_y_max), CAMERA_PICTURE_SIZE_HARD_LIMIT) return TRUE -/obj/item/camera/AltClick(mob/user) - if(!user.can_perform_action(src)) - return +/obj/item/camera/click_alt(mob/user) adjust_zoom(user) + return CLICK_ACTION_SUCCESS /obj/item/camera/attack(mob/living/carbon/human/M, mob/user) return @@ -206,7 +205,7 @@ turfs += placeholder for(var/mob/M in placeholder) mobs += M - if(locate(/obj/item/areaeditor/blueprints) in placeholder) + if(locate(/obj/item/blueprints) in placeholder) blueprints = TRUE // do this before picture is taken so we can reveal revenants for the photo @@ -251,11 +250,11 @@ to_chat(user, span_notice("[pictures_left] photos left.")) if(can_customise) - var/customise = tgui_alert(user, "Do you want to customize the photo?", "Customization", list("Yes", "No")) + var/customise = user.is_holding(new_photo) && tgui_alert(user, "Do you want to customize the photo?", "Customization", list("Yes", "No")) if(customise == "Yes") - var/name1 = tgui_input_text(user, "Set a name for this photo, or leave blank.", "Name", max_length = 32) - var/desc1 = tgui_input_text(user, "Set a description to add to photo, or leave blank.", "Description", max_length = 128) - var/caption = tgui_input_text(user, "Set a caption for this photo, or leave blank.", "Caption", max_length = 256) + var/name1 = user.is_holding(new_photo) && tgui_input_text(user, "Set a name for this photo, or leave blank.", "Name", max_length = 32) + var/desc1 = user.is_holding(new_photo) && tgui_input_text(user, "Set a description to add to photo, or leave blank.", "Description", max_length = 128) + var/caption = user.is_holding(new_photo) && tgui_input_text(user, "Set a caption for this photo, or leave blank.", "Caption", max_length = 256) if(name1) picture.picture_name = name1 if(desc1) diff --git a/code/modules/plumbing/ducts.dm b/code/modules/plumbing/ducts.dm index 33073ae910f..a7990f65ce5 100644 --- a/code/modules/plumbing/ducts.dm +++ b/code/modules/plumbing/ducts.dm @@ -343,9 +343,13 @@ All the important duct code: /obj/item/stack/ducts/attack_self(mob/user) var/new_layer = tgui_input_list(user, "Select a layer", "Layer", GLOB.plumbing_layers, duct_layer) + if(!user.is_holding(src)) + return if(new_layer) duct_layer = new_layer var/new_color = tgui_input_list(user, "Select a color", "Color", GLOB.pipe_paint_colors, duct_color) + if(!user.is_holding(src)) + return if(new_color) duct_color = new_color add_atom_colour(GLOB.pipe_paint_colors[new_color], FIXED_COLOUR_PRIORITY) diff --git a/code/modules/plumbing/plumbers/_plumb_machinery.dm b/code/modules/plumbing/plumbers/_plumb_machinery.dm index 418df177465..8baf59508b8 100644 --- a/code/modules/plumbing/plumbers/_plumb_machinery.dm +++ b/code/modules/plumbing/plumbers/_plumb_machinery.dm @@ -26,8 +26,6 @@ . = ..() . += span_notice("The maximum volume display reads: [reagents.maximum_volume] units.") -/obj/machinery/plumbing/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation /obj/machinery/plumbing/wrench_act(mob/living/user, obj/item/tool) . = ..() @@ -35,9 +33,9 @@ return ITEM_INTERACT_SUCCESS /obj/machinery/plumbing/plunger_act(obj/item/plunger/P, mob/living/user, reinforced) - to_chat(user, span_notice("You start furiously plunging [name].")) + user.balloon_alert_to_viewers("furiously plunging...") if(do_after(user, 3 SECONDS, target = src)) - to_chat(user, span_notice("You finish plunging the [name].")) + user.balloon_alert_to_viewers("finished plunging") reagents.expose(get_turf(src), TOUCH) //splash on the floor reagents.clear_reagents() diff --git a/code/modules/plumbing/plumbers/filter.dm b/code/modules/plumbing/plumbers/filter.dm index 633f70830f0..c4df35164f0 100644 --- a/code/modules/plumbing/plumbers/filter.dm +++ b/code/modules/plumbing/plumbers/filter.dm @@ -30,7 +30,7 @@ data["right"] = english_right return data -/obj/machinery/plumbing/filter/ui_act(action, params) +/obj/machinery/plumbing/filter/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() if(.) return @@ -42,6 +42,8 @@ var/selected_reagent = tgui_input_list(usr, "Select [which] reagent", "Reagent", GLOB.name2reagent) if(!selected_reagent) return TRUE + if(QDELETED(ui) || ui.status != UI_INTERACTIVE) + return FALSE var/datum/reagent/chem_id = GLOB.name2reagent[selected_reagent] if(!chem_id) @@ -69,5 +71,3 @@ if(english_right.Find(chem_name)) english_right -= chem_name right -= chem_id - - diff --git a/code/modules/plumbing/plumbers/iv_drip.dm b/code/modules/plumbing/plumbers/iv_drip.dm index 7275212ee76..f9a5ae47598 100644 --- a/code/modules/plumbing/plumbers/iv_drip.dm +++ b/code/modules/plumbing/plumbers/iv_drip.dm @@ -23,14 +23,12 @@ return CONTEXTUAL_SCREENTIP_SET /obj/machinery/iv_drip/plumbing/plunger_act(obj/item/plunger/P, mob/living/user, reinforced) - to_chat(user, span_notice("You start furiously plunging [name].")) + user.balloon_alert_to_viewers("furiously plunging...", "plunging iv drip...") if(do_after(user, 3 SECONDS, target = src)) - to_chat(user, span_notice("You finish plunging the [name].")) + user.balloon_alert_to_viewers("finished plunging") reagents.expose(get_turf(src), TOUCH) //splash on the floor reagents.clear_reagents() -/obj/machinery/iv_drip/plumbing/can_use_alt_click(mob/user) - return FALSE //Alt click is used for rotation /obj/machinery/iv_drip/plumbing/wrench_act(mob/living/user, obj/item/tool) if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN) diff --git a/code/modules/plumbing/plumbers/reaction_chamber.dm b/code/modules/plumbing/plumbers/reaction_chamber.dm index 72caa603767..9bdac2f98b2 100644 --- a/code/modules/plumbing/plumbers/reaction_chamber.dm +++ b/code/modules/plumbing/plumbers/reaction_chamber.dm @@ -107,6 +107,8 @@ var/selected_reagent = tgui_input_list(ui.user, "Select reagent", "Reagent", GLOB.name2reagent) if(!selected_reagent) return FALSE + if(QDELETED(ui) || ui.status != UI_INTERACTIVE) + return FALSE var/datum/reagent/input_reagent = GLOB.name2reagent[selected_reagent] if(!input_reagent) diff --git a/code/modules/power/apc/apc_tool_act.dm b/code/modules/power/apc/apc_tool_act.dm index 00d3fc7a538..6a8835cd5b7 100644 --- a/code/modules/power/apc/apc_tool_act.dm +++ b/code/modules/power/apc/apc_tool_act.dm @@ -1,10 +1,7 @@ //attack with an item - open/close cover, insert cell, or (un)lock interface -/obj/machinery/power/apc/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) - . = ..() - if(.) - return . - +/obj/machinery/power/apc/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + . = NONE if(HAS_TRAIT(tool, TRAIT_APC_SHOCKING)) . = fork_outlet_act(user, tool) if(.) @@ -17,7 +14,7 @@ if(istype(tool, /obj/item/stock_parts/cell)) . = cell_act(user, tool) else if(istype(tool, /obj/item/stack/cable_coil)) - . = cable_act(user, tool, is_right_clicking) + . = cable_act(user, tool, LAZYACCESS(modifiers, RIGHT_CLICK)) else if(istype(tool, /obj/item/electronics/apc)) . = electronics_act(user, tool) else if(istype(tool, /obj/item/electroadaptive_pseudocircuit)) @@ -26,7 +23,7 @@ . = wallframe_act(user, tool) if(.) return . - + if(panel_open && !opened && is_wire_tool(tool)) wires.interact(user) return ITEM_INTERACT_SUCCESS @@ -73,44 +70,59 @@ update_appearance() return ITEM_INTERACT_SUCCESS +/// Checks if we can place a terminal on the APC +/obj/machinery/power/apc/proc/can_place_terminal(mob/living/user, obj/item/stack/cable_coil/installing_cable, silent = TRUE) + if(!opened) + return FALSE + var/turf/host_turf = get_turf(src) + if(host_turf.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) + if(!silent && user) + balloon_alert(user, "remove the floor plating!") + return FALSE + if(!isnull(terminal)) + if(!silent && user) + balloon_alert(user, "already wired!") + return FALSE + if(!has_electronics) + if(!silent && user) + balloon_alert(user, "no board to wire!") + return FALSE + if(panel_open) + if(!silent && user) + balloon_alert(user, "wires prevent placing a terminal!") + return FALSE + if(installing_cable.get_amount() < 10) + if(!silent && user) + balloon_alert(user, "need ten lengths of cable!") + return FALSE + return TRUE + /// Called when we interact with the APC with a cable, attempts to wire the APC and create a terminal /obj/machinery/power/apc/proc/cable_act(mob/living/user, obj/item/stack/cable_coil/installing_cable, is_right_clicking) if(!opened) return NONE - - var/turf/host_turf = get_turf(src) - if(!host_turf) - CRASH("cable_act on APC when it's not on a turf") - if(host_turf.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) - balloon_alert(user, "remove the floor plating!") - return ITEM_INTERACT_BLOCKING - if(terminal) - balloon_alert(user, "already wired!") - return ITEM_INTERACT_BLOCKING - if(!has_electronics) - balloon_alert(user, "no board to wire!") - return ITEM_INTERACT_BLOCKING - - if(installing_cable.get_amount() < 10) - balloon_alert(user, "need ten lengths of cable!") + if(!can_place_terminal(user, installing_cable, silent = FALSE)) return ITEM_INTERACT_BLOCKING var/terminal_cable_layer = cable_layer // Default to machine's cable layer if(is_right_clicking) var/choice = tgui_input_list(user, "Select Power Input Cable Layer", "Select Cable Layer", GLOB.cable_name_to_layer) - if(isnull(choice)) + if(isnull(choice) \ + || !user.is_holding(installing_cable) \ + || !user.Adjacent(src) \ + || user.incapacitated() \ + || !can_place_terminal(user, installing_cable, silent = TRUE) \ + ) return ITEM_INTERACT_BLOCKING terminal_cable_layer = GLOB.cable_name_to_layer[choice] - user.visible_message(span_notice("[user.name] adds cables to the APC frame.")) - balloon_alert(user, "adding cables to the frame...") - playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE) + user.visible_message(span_notice("[user.name] starts addding cables to the APC frame.")) + balloon_alert(user, "adding cables...") + playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE) if(!do_after(user, 2 SECONDS, target = src)) return ITEM_INTERACT_BLOCKING - if(installing_cable.get_amount() < 10 || !installing_cable) - return ITEM_INTERACT_BLOCKING - if(terminal || !opened || !has_electronics) + if(!can_place_terminal(user, installing_cable, silent = TRUE)) return ITEM_INTERACT_BLOCKING var/turf/our_turf = get_turf(src) var/obj/structure/cable/cable_node = our_turf.get_cable_node(terminal_cable_layer) @@ -118,7 +130,8 @@ do_sparks(5, TRUE, src) return ITEM_INTERACT_BLOCKING installing_cable.use(10) - balloon_alert(user, "cables added to the frame") + user.visible_message(span_notice("[user.name] adds cables to the APC frame.")) + balloon_alert(user, "cables added") make_terminal(terminal_cable_layer) terminal.connect_to_network() return ITEM_INTERACT_SUCCESS @@ -127,7 +140,7 @@ /obj/machinery/power/apc/proc/electronics_act(mob/living/user, obj/item/electronics/apc/installing_board) if(!opened) return NONE - + if(has_electronics) balloon_alert(user, "there is already a board!") return ITEM_INTERACT_BLOCKING diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm index a7013595543..0a698817602 100644 --- a/code/modules/power/lighting/light.dm +++ b/code/modules/power/lighting/light.dm @@ -118,9 +118,8 @@ RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) AddElement(/datum/element/atmos_sensitive, mapload) find_and_hang_on_wall(custom_drop_callback = CALLBACK(src, PROC_REF(knock_down))) - return INITIALIZE_HINT_LATELOAD -/obj/machinery/light/LateInitialize() +/obj/machinery/light/post_machine_initialize() . = ..() #ifndef MAP_TEST switch(fitting) diff --git a/code/modules/power/pipecleaners.dm b/code/modules/power/pipecleaners.dm index 2a41c70bdfe..7f1ef8fc2e3 100644 --- a/code/modules/power/pipecleaners.dm +++ b/code/modules/power/pipecleaners.dm @@ -163,10 +163,9 @@ By design, d1 is the smallest direction and d2 is the highest stored.color = colorC stored.update_appearance() -/obj/structure/pipe_cleaner/AltClick(mob/living/user) - if(!user.can_perform_action(src)) - return +/obj/structure/pipe_cleaner/click_alt(mob/living/user) cut_pipe_cleaner(user) + return CLICK_ACTION_SUCCESS /////////////////////////////////////////////// // The pipe cleaner coil object, used for laying pipe cleaner diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm index 84542805d48..e4c1617c0f0 100644 --- a/code/modules/power/port_gen.dm +++ b/code/modules/power/port_gen.dm @@ -98,7 +98,7 @@ var/obj/S = sheet_path sheet_name = initial(S.name) -/obj/machinery/power/port_gen/pacman/Destroy() +/obj/machinery/power/port_gen/pacman/on_deconstruction(disassembled) DropFuel() return ..() diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index ce912027225..c9cbb0d3ecc 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -50,9 +50,9 @@ . = ..() if(can_change_cable_layer) if(!QDELETED(powernet)) - . += span_notice("It's operating on the [lowertext(GLOB.cable_layer_to_name["[cable_layer]"])].") + . += span_notice("It's operating on the [LOWER_TEXT(GLOB.cable_layer_to_name["[cable_layer]"])].") else - . += span_warning("It's disconnected from the [lowertext(GLOB.cable_layer_to_name["[cable_layer]"])].") + . += span_warning("It's disconnected from the [LOWER_TEXT(GLOB.cable_layer_to_name["[cable_layer]"])].") . += span_notice("It's power line can be changed with a [EXAMINE_HINT("multitool")].") /obj/machinery/power/multitool_act(mob/living/user, obj/item/tool) diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm index 9f19774cc61..932aef0e8e5 100644 --- a/code/modules/power/singularity/containment_field.dm +++ b/code/modules/power/singularity/containment_field.dm @@ -29,6 +29,7 @@ COMSIG_ATOM_ENTERED = PROC_REF(on_entered), ) AddElement(/datum/element/connect_loc, loc_connections) + AddElement(/datum/element/give_turf_traits, string_list(list(TRAIT_CONTAINMENT_FIELD))) /obj/machinery/field/containment/Destroy() if(field_gen_1) diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index a360fc12145..38f18d7d627 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -346,8 +346,6 @@ return return ..() -/obj/machinery/power/emitter/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation /obj/machinery/power/emitter/proc/integrate(obj/item/gun/energy/energy_gun, mob/user) if(!istype(energy_gun, /obj/item/gun/energy)) diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index 527ce9c560b..ba9fde43d49 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -208,6 +208,7 @@ no power level overlay is currently in the overlays list. air_update_turf(TRUE, FALSE) INVOKE_ASYNC(src, PROC_REF(cleanup)) addtimer(CALLBACK(src, PROC_REF(cool_down)), 5 SECONDS) + RemoveElement(/datum/element/give_turf_traits, string_list(list(TRAIT_CONTAINMENT_FIELD))) /obj/machinery/field/generator/proc/cool_down() if(active || warming_up <= 0) @@ -220,6 +221,7 @@ no power level overlay is currently in the overlays list. /obj/machinery/field/generator/proc/turn_on() active = FG_CHARGING addtimer(CALLBACK(src, PROC_REF(warm_up)), 5 SECONDS) + AddElement(/datum/element/give_turf_traits, string_list(list(TRAIT_CONTAINMENT_FIELD))) /obj/machinery/field/generator/proc/warm_up() if(!active) diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 5b712d52da2..d47d7536094 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -386,16 +386,8 @@ /obj/singularity/proc/can_move(turf/considered_turf) if(!considered_turf) return FALSE - if((locate(/obj/machinery/field/containment) in considered_turf) || (locate(/obj/machinery/shieldwall) in considered_turf)) + if (HAS_TRAIT(considered_turf, TRAIT_CONTAINMENT_FIELD)) return FALSE - else if(locate(/obj/machinery/field/generator) in considered_turf) - var/obj/machinery/field/generator/check_generator = locate(/obj/machinery/field/generator) in considered_turf - if(check_generator?.active) - return FALSE - else if(locate(/obj/machinery/power/shieldwallgen) in considered_turf) - var/obj/machinery/power/shieldwallgen/check_shield = locate(/obj/machinery/power/shieldwallgen) in considered_turf - if(check_shield?.active) - return FALSE return TRUE /obj/singularity/proc/event() @@ -482,3 +474,16 @@ /// Special singularity that spawns for shuttle events only /obj/singularity/shuttle_event anchored = FALSE + +/// Special singularity spawned by being sucked into a black hole during emagged orion trail. +/obj/singularity/orion + move_self = FALSE + +/obj/singularity/orion/Initialize(mapload) + . = ..() + var/datum/component/singularity/singularity = singularity_component.resolve() + singularity?.grav_pull = 1 + +/obj/singularity/orion/process(seconds_per_tick) + if(SPT_PROB(0.5, seconds_per_tick)) + mezzer() diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index c6fa9274cb3..2aa5247451d 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -112,55 +112,42 @@ //building and linking a terminal if(istype(item, /obj/item/stack/cable_coil)) - var/dir = get_dir(user,src) - if(dir & (dir-1))//we don't want diagonal click - return - - if(terminal) //is there already a terminal ? - to_chat(user, span_warning("This SMES already has a power terminal!")) - return - - if(!panel_open) //is the panel open ? - to_chat(user, span_warning("You must open the maintenance panel first!")) - return - - var/turf/turf = get_turf(user) - if (turf.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) //can we get to the underfloor? - to_chat(user, span_warning("You must first remove the floor plating!")) - return - - - var/obj/item/stack/cable_coil/cable = item - if(cable.get_amount() < 10) - to_chat(user, span_warning("You need more wires!")) + if(!can_place_terminal(user, item, silent = FALSE)) return var/terminal_cable_layer if(LAZYACCESS(params2list(params), RIGHT_CLICK)) var/choice = tgui_input_list(user, "Select Power Input Cable Layer", "Select Cable Layer", GLOB.cable_name_to_layer) - if(isnull(choice)) + if(isnull(choice) \ + || !user.is_holding(item) \ + || !user.Adjacent(src) \ + || user.incapacitated() \ + || !can_place_terminal(user, item, silent = TRUE) \ + ) return terminal_cable_layer = GLOB.cable_name_to_layer[choice] - to_chat(user, span_notice("You start building the power terminal...")) - playsound(src.loc, 'sound/items/deconstruct.ogg', 50, TRUE) + user.visible_message(span_notice("[user.name] starts adding cables to [src].")) + balloon_alert(user, "adding cables...") + playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE) - if(do_after(user, 2 SECONDS, target = src)) - if(cable.get_amount() < 10 || !cable) - return - var/obj/structure/cable/connected_cable = turf.get_cable_node(terminal_cable_layer) //get the connecting node cable, if there's one - if (prob(50) && electrocute_mob(user, connected_cable, connected_cable, 1, TRUE)) //animate the electrocution if uncautious and unlucky - do_sparks(5, TRUE, src) - return - if(!terminal) - cable.use(10) - user.visible_message(span_notice("[user.name] builds a power terminal."),\ - span_notice("You build the power terminal.")) - - //build the terminal and link it to the network - make_terminal(turf, terminal_cable_layer) - terminal.connect_to_network() - connect_to_network() + if(!do_after(user, 2 SECONDS, target = src)) + return + if(!can_place_terminal(user, item, silent = TRUE)) + return + var/obj/item/stack/cable_coil/cable = item + var/turf/turf = get_turf(user) + var/obj/structure/cable/connected_cable = turf.get_cable_node(terminal_cable_layer) //get the connecting node cable, if there's one + if (prob(50) && electrocute_mob(user, connected_cable, connected_cable, 1, TRUE)) //animate the electrocution if uncautious and unlucky + do_sparks(5, TRUE, src) + return + cable.use(10) + user.visible_message(span_notice("[user.name] adds cables to [src]")) + balloon_alert(user, "cables added") + //build the terminal and link it to the network + make_terminal(turf, terminal_cable_layer) + terminal.connect_to_network() + connect_to_network() return //crowbarring it ! @@ -175,6 +162,31 @@ return ..() +/// Checks if we're in a valid state to place a terminal +/obj/machinery/power/smes/proc/can_place_terminal(mob/living/user, obj/item/stack/cable_coil/installing_cable, silent = TRUE) + var/set_dir = get_dir(user, src) + if(set_dir & (set_dir - 1))//we don't want diagonal click + return FALSE + + var/turf/terminal_turf = get_turf(user) + if(!panel_open) + if(!silent && user) + balloon_alert(user, "open the maintenance panel!") + return FALSE + if(terminal_turf.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) + if(!silent && user) + balloon_alert(user, "remove the floor plating!") + return FALSE + if(terminal) + if(!silent && user) + balloon_alert(user, "already wired!") + return FALSE + if(installing_cable.get_amount() < 10) + if(!silent && user) + balloon_alert(user, "need ten lengths of cable!") + return FALSE + return TRUE + /obj/machinery/power/smes/wirecutter_act(mob/living/user, obj/item/item) //disassembling the terminal . = ..() diff --git a/code/modules/power/terminal.dm b/code/modules/power/terminal.dm index 4c861a4bb4b..04b9ab8798b 100644 --- a/code/modules/power/terminal.dm +++ b/code/modules/power/terminal.dm @@ -26,9 +26,9 @@ /obj/machinery/power/terminal/examine(mob/user) . = ..() if(!QDELETED(powernet)) - . += span_notice("It's operating on the [lowertext(GLOB.cable_layer_to_name["[cable_layer]"])].") + . += span_notice("It's operating on the [LOWER_TEXT(GLOB.cable_layer_to_name["[cable_layer]"])].") else - . += span_warning("It's disconnected from the [lowertext(GLOB.cable_layer_to_name["[cable_layer]"])].") + . += span_warning("It's disconnected from the [LOWER_TEXT(GLOB.cable_layer_to_name["[cable_layer]"])].") /obj/machinery/power/terminal/should_have_node() return TRUE diff --git a/code/modules/power/turbine/turbine.dm b/code/modules/power/turbine/turbine.dm index 21269c90d37..590b135ad9a 100644 --- a/code/modules/power/turbine/turbine.dm +++ b/code/modules/power/turbine/turbine.dm @@ -43,7 +43,7 @@ register_context() -/obj/machinery/power/turbine/LateInitialize() +/obj/machinery/power/turbine/post_machine_initialize() . = ..() activate_parts() diff --git a/code/modules/power/turbine/turbine_computer.dm b/code/modules/power/turbine/turbine_computer.dm index 9e0f5bdaa46..f983e11c1f1 100644 --- a/code/modules/power/turbine/turbine_computer.dm +++ b/code/modules/power/turbine/turbine_computer.dm @@ -9,11 +9,7 @@ ///Easy way to connect a computer and a turbine roundstart by setting an id on both this and the core_rotor var/mapping_id -/obj/machinery/computer/turbine_computer/Initialize(mapload) - . = ..() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/computer/turbine_computer/LateInitialize() +/obj/machinery/computer/turbine_computer/post_machine_initialize() . = ..() locate_machinery() diff --git a/code/modules/procedural_mapping/mapGenerator.dm b/code/modules/procedural_mapping/mapGenerator.dm index 420ac9c8d79..58ff5641907 100644 --- a/code/modules/procedural_mapping/mapGenerator.dm +++ b/code/modules/procedural_mapping/mapGenerator.dm @@ -136,40 +136,36 @@ // HERE BE DEBUG DRAGONS // /////////////////////////// -/client/proc/debugNatureMapGenerator() - set name = "Test Nature Map Generator" - set category = "Debug" - +ADMIN_VERB(debug_nature_map_generator, R_DEBUG, "Test Nature Map Generator", "Test the nature map generator", ADMIN_CATEGORY_DEBUG) var/datum/map_generator/nature/N = new() - var/startInput = input(usr, "Start turf of Map, (X;Y;Z)", "Map Gen Settings", "1;1;1") as text|null + var/startInput = input(user, "Start turf of Map, (X;Y;Z)", "Map Gen Settings", "1;1;1") as text|null if (isnull(startInput)) return - var/endInput = input(usr, "End turf of Map (X;Y;Z)", "Map Gen Settings", "[world.maxx];[world.maxy];[mob ? mob.z : 1]") as text|null - + var/endInput = input(user, "End turf of Map (X;Y;Z)", "Map Gen Settings", "[world.maxx];[world.maxy];[user.mob.z]") as text|null if (isnull(endInput)) return //maxx maxy and current z so that if you fuck up, you only fuck up one entire z level instead of the entire universe if(!startInput || !endInput) - to_chat(src, "Missing Input") + to_chat(user, "Missing Input") return var/list/startCoords = splittext(startInput, ";") var/list/endCoords = splittext(endInput, ";") if(!startCoords || !endCoords) - to_chat(src, "Invalid Coords") - to_chat(src, "Start Input: [startInput]") - to_chat(src, "End Input: [endInput]") + to_chat(user, "Invalid Coords") + to_chat(user, "Start Input: [startInput]") + to_chat(user, "End Input: [endInput]") return var/turf/Start = locate(text2num(startCoords[1]),text2num(startCoords[2]),text2num(startCoords[3])) var/turf/End = locate(text2num(endCoords[1]),text2num(endCoords[2]),text2num(endCoords[3])) if(!Start || !End) - to_chat(src, "Invalid Turfs") - to_chat(src, "Start Coords: [startCoords[1]] - [startCoords[2]] - [startCoords[3]]") - to_chat(src, "End Coords: [endCoords[1]] - [endCoords[2]] - [endCoords[3]]") + to_chat(user, "Invalid Turfs") + to_chat(user, "Start Coords: [startCoords[1]] - [startCoords[2]] - [startCoords[3]]") + to_chat(user, "End Coords: [endCoords[1]] - [endCoords[2]] - [endCoords[3]]") return var/static/list/clusters = list( @@ -191,7 +187,7 @@ var/theCluster = 0 if(moduleClusters != "None") if(!clusters[moduleClusters]) - to_chat(src, "Invalid Cluster Flags") + to_chat(user, "Invalid Cluster Flags") return theCluster = clusters[moduleClusters] else @@ -202,9 +198,9 @@ M.clusterCheckFlags = theCluster - to_chat(src, "Defining Region") + to_chat(user, "Defining Region") N.defineRegion(Start, End) - to_chat(src, "Region Defined") - to_chat(src, "Generating Region") + to_chat(user, "Region Defined") + to_chat(user, "Generating Region") N.generate() - to_chat(src, "Generated Region") + to_chat(user, "Generated Region") diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index 791055fd2d2..b206e1977f4 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -485,7 +485,7 @@ ///Installs a new suppressor, assumes that the suppressor is already in the contents of src /obj/item/gun/ballistic/proc/install_suppressor(obj/item/suppressor/S) suppressed = S - w_class += S.w_class //so pistols do not fit in pockets when suppressed + update_weight_class(w_class + S.w_class) //so pistols do not fit in pockets when suppressed update_appearance() /obj/item/gun/ballistic/clear_suppressor() @@ -493,21 +493,19 @@ return if(isitem(suppressed)) var/obj/item/I = suppressed - w_class -= I.w_class + update_weight_class(w_class - I.w_class) return ..() -/obj/item/gun/ballistic/AltClick(mob/user) - if (unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY)) - reskin_obj(user) - return - if(loc == user) - if(suppressed && can_unsuppress) - var/obj/item/suppressor/S = suppressed - if(!user.is_holding(src)) - return ..() - balloon_alert(user, "[S.name] removed") - user.put_in_hands(S) - clear_suppressor() +/obj/item/gun/ballistic/click_alt(mob/user) + if(!suppressed || !can_unsuppress) + return CLICK_ACTION_BLOCKING + var/obj/item/suppressor/S = suppressed + if(!user.is_holding(src)) + return CLICK_ACTION_BLOCKING + balloon_alert(user, "[S.name] removed") + user.put_in_hands(S) + clear_suppressor() + return CLICK_ACTION_SUCCESS ///Prefire empty checks for the bolt drop /obj/item/gun/ballistic/proc/prefire_empty_checks() @@ -666,7 +664,7 @@ GLOBAL_LIST_INIT(gun_saw_types, typecacheof(list( if(handle_modifications) name = "sawn-off [src.name]" desc = sawn_desc - w_class = WEIGHT_CLASS_NORMAL + update_weight_class(WEIGHT_CLASS_NORMAL) //The file might not have a "gun" icon, let's prepare for this lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm index 3d6940692d8..8c6e2ae7cbd 100644 --- a/code/modules/projectiles/guns/ballistic/automatic.dm +++ b/code/modules/projectiles/guns/ballistic/automatic.dm @@ -260,13 +260,12 @@ . += span_notice("It seems like you could use an empty hand to remove the magazine.") -/obj/item/gun/ballistic/automatic/l6_saw/AltClick(mob/user) - if(!user.can_perform_action(src)) - return +/obj/item/gun/ballistic/automatic/l6_saw/click_alt(mob/user) cover_open = !cover_open balloon_alert(user, "cover [cover_open ? "opened" : "closed"]") playsound(src, 'sound/weapons/gun/l6/l6_door.ogg', 60, TRUE) update_appearance() + return CLICK_ACTION_SUCCESS /obj/item/gun/ballistic/automatic/l6_saw/update_icon_state() . = ..() diff --git a/code/modules/projectiles/guns/ballistic/bows/_bow.dm b/code/modules/projectiles/guns/ballistic/bows/_bow.dm index c356d5b266c..86094d0fe17 100644 --- a/code/modules/projectiles/guns/ballistic/bows/_bow.dm +++ b/code/modules/projectiles/guns/ballistic/bows/_bow.dm @@ -29,13 +29,14 @@ . = ..() icon_state = chambered ? "[base_icon_state]_[drawn ? "drawn" : "nocked"]" : "[base_icon_state]" -/obj/item/gun/ballistic/bow/AltClick(mob/user) +/obj/item/gun/ballistic/bow/click_alt(mob/user) if(isnull(chambered)) - return ..() + return CLICK_ACTION_BLOCKING user.put_in_hands(chambered) chambered = magazine.get_round() update_appearance() + return CLICK_ACTION_SUCCESS /obj/item/gun/ballistic/bow/proc/drop_arrow() chambered.forceMove(drop_location()) diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index 373607e53dd..e142616cbd4 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -37,9 +37,9 @@ ..() chamber_round() -/obj/item/gun/ballistic/revolver/AltClick(mob/user) - ..() +/obj/item/gun/ballistic/revolver/click_alt(mob/user) spin() + return CLICK_ACTION_SUCCESS /obj/item/gun/ballistic/revolver/fire_sounds() var/frequency_to_use = sin((90/magazine?.max_ammo) * get_ammo(TRUE, FALSE)) // fucking REVOLVERS diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm index 37990971138..c584359b8ce 100644 --- a/code/modules/projectiles/guns/ballistic/shotgun.dm +++ b/code/modules/projectiles/guns/ballistic/shotgun.dm @@ -85,6 +85,7 @@ w_class = WEIGHT_CLASS_HUGE semi_auto = TRUE accepted_magazine_type = /obj/item/ammo_box/magazine/internal/shot/tube + interaction_flags_click = NEED_DEXTERITY|NEED_HANDS /// If defined, the secondary tube is this type, if you want different shell loads var/alt_mag_type /// If TRUE, we're drawing from the alternate_magazine @@ -131,10 +132,9 @@ else balloon_alert(user, "switched to tube A") -/obj/item/gun/ballistic/shotgun/automatic/dual_tube/AltClick(mob/living/user) - if(!user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS)) - return +/obj/item/gun/ballistic/shotgun/automatic/dual_tube/click_alt(mob/living/user) rack() + return CLICK_ACTION_SUCCESS // Bulldog shotgun // @@ -288,10 +288,6 @@ can_be_sawn_off = TRUE pb_knockback = 3 // it's a super shotgun! -/obj/item/gun/ballistic/shotgun/doublebarrel/AltClick(mob/user) - . = ..() - if(unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY)) - reskin_obj(user) /obj/item/gun/ballistic/shotgun/doublebarrel/sawoff(mob/user) . = ..() diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 27e93653a77..1d53eff0f9b 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -475,7 +475,7 @@ if(!trajectory) qdel(src) return FALSE - if(impacted[A]) // NEVER doublehit + if(impacted[A.weak_reference]) // NEVER doublehit return FALSE var/datum/point/point_cache = trajectory.copy_to() var/turf/T = get_turf(A) @@ -528,7 +528,7 @@ if(QDELETED(src) || !T || !target) return // 2. - impacted[target] = TRUE //hash lookup > in for performance in hit-checking + impacted[WEAKREF(target)] = TRUE //hash lookup > in for performance in hit-checking // 3. var/mode = prehit_pierce(target) if(mode == PROJECTILE_DELETE_WITHOUT_HITTING) @@ -605,7 +605,7 @@ //Returns true if the target atom is on our current turf and above the right layer //If direct target is true it's the originally clicked target. /obj/projectile/proc/can_hit_target(atom/target, direct_target = FALSE, ignore_loc = FALSE, cross_failed = FALSE) - if(QDELETED(target) || impacted[target]) + if(QDELETED(target) || impacted[target.weak_reference]) return FALSE if(!ignore_loc && (loc != target.loc) && !(can_hit_turfs && direct_target && loc == target)) return FALSE @@ -693,7 +693,7 @@ * Used to not even attempt to Bump() or fail to Cross() anything we already hit. */ /obj/projectile/CanPassThrough(atom/blocker, movement_dir, blocker_opinion) - return impacted[blocker] ? TRUE : ..() + return ..() || impacted[blocker.weak_reference] /** * Projectile moved: @@ -1204,10 +1204,8 @@ var/turf/startloc = get_turf(src) var/obj/projectile/bullet = new projectile_type(startloc) bullet.starting = startloc - var/list/ignore = list() for (var/atom/thing as anything in ignore_targets) - ignore[thing] = TRUE - bullet.impacted += ignore + bullet.impacted[WEAKREF(thing)] = TRUE bullet.firer = firer || src bullet.fired_from = src bullet.yo = target.y - startloc.y diff --git a/code/modules/reagents/chemistry/chem_wiki_render.dm b/code/modules/reagents/chemistry/chem_wiki_render.dm index a2ac0af8ffb..99116adc84b 100644 --- a/code/modules/reagents/chemistry/chem_wiki_render.dm +++ b/code/modules/reagents/chemistry/chem_wiki_render.dm @@ -1,10 +1,6 @@ -//Generates a wikitable txt file for use with the wiki - does not support productless reactions at the moment -/client/proc/generate_wikichem_list() - set category = "Debug" - set name = "Parse Wikichems" - +ADMIN_VERB(generate_wikichem_list, R_DEBUG, "Parse Wikichems", "Parse and generate a text file for wikichem.", ADMIN_CATEGORY_DEBUG) //If we're a reaction product - var/prefix_reaction = {"{| class=\"wikitable sortable\" style=\"width:100%; text-align:left; border: 3px solid #FFDD66; cellspacing=0; cellpadding=2; background-color:white;\" + var/static/prefix_reaction = {"{| class=\"wikitable sortable\" style=\"width:100%; text-align:left; border: 3px solid #FFDD66; cellspacing=0; cellpadding=2; background-color:white;\" ! scope=\"col\" style='width:150px; background-color:#FFDD66;'|Name ! scope=\"col\" class=\"unsortable\" style='background-color:#FFDD66;'|Formula ! scope=\"col\" class=\"unsortable\" style='background-color:#FFDD66; width:170px;'|Reaction conditions @@ -13,9 +9,9 @@ |- "} - var/input_text = tgui_input_text(usr, "Input a name of a reagent, or a series of reagents split with a comma (no spaces) to get it's wiki table entry", "Recipe") //95% of the time, the reagent type is a lowercase, no spaces / underscored version of the name + var/input_text = tgui_input_text(user, "Input a name of a reagent, or a series of reagents split with a comma (no spaces) to get it's wiki table entry", "Recipe") //95% of the time, the reagent type is a lowercase, no spaces / underscored version of the name if(!input_text) - to_chat(usr, "Input was blank!") + to_chat(user, "Input was blank!") return text2file(prefix_reaction, "[GLOB.log_directory]/chem_parse.txt") var/list/names = splittext("[input_text]", ",") @@ -23,13 +19,13 @@ for(var/name in names) var/datum/reagent/reagent = find_reagent_object_from_type(get_chem_id(name)) if(!reagent) - to_chat(usr, "Could not find [name]. Skipping.") + to_chat(user, "Could not find [name]. Skipping.") continue //Get reaction var/list/reactions = GLOB.chemical_reactions_list_product_index[reagent.type] if(!length(reactions)) - to_chat(usr, "Could not find [name] reaction! Continuing anyways.") + to_chat(user, "Could not find [name] reaction! Continuing anyways.") var/single_parse = generate_chemwiki_line(reagent, null) text2file(single_parse, "[GLOB.log_directory]/chem_parse.txt") continue @@ -38,8 +34,7 @@ var/single_parse = generate_chemwiki_line(reagent, reaction) text2file(single_parse, "[GLOB.log_directory]/chem_parse.txt") text2file("|}", "[GLOB.log_directory]/chem_parse.txt") //Cap off the table - to_chat(usr, "Done! Saved file to (wherever your root folder is, i.e. where the DME is)/[GLOB.log_directory]/chem_parse.txt OR use the Get Current Logs verb under the Admin tab. (if you click Open, and it does nothing, that's because you've not set a .txt default program! Try downloading it instead, and use that file to set a default program! Have a nice day!") - + to_chat(user, "Done! Saved file to (wherever your root folder is, i.e. where the DME is)/[GLOB.log_directory]/chem_parse.txt OR use the Get Current Logs verb under the Admin tab. (if you click Open, and it does nothing, that's because you've not set a .txt default program! Try downloading it instead, and use that file to set a default program! Have a nice day!") /// Generate the big list of reagent based reactions. /proc/generate_chemwiki_line(datum/reagent/reagent, datum/chemical_reaction/reaction) diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 80afcc534b0..6984c042f55 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -458,7 +458,7 @@ return ITEM_INTERACT_SUCCESS return ITEM_INTERACT_BLOCKING -/obj/machinery/chem_dispenser/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) +/obj/machinery/chem_dispenser/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(is_reagent_container(tool) && !(tool.item_flags & ABSTRACT) && tool.is_open_container()) //SKYRAT EDIT ADDITION START - CHEMISTRY QOL var/obj/item/reagent_containers/container = tool @@ -467,12 +467,12 @@ transferAmounts = container.possible_transfer_amounts //SKYRAT EDIT ADDITION END if(!user.transferItemToLoc(tool, src)) - return ..() + return ITEM_INTERACT_BLOCKING replace_beaker(user, tool) ui_interact(user) return ITEM_INTERACT_SUCCESS - return ..() + return NONE /obj/machinery/chem_dispenser/get_cell() return cell @@ -569,8 +569,6 @@ /obj/machinery/chem_dispenser/attack_ai_secondary(mob/user, list/modifiers) return attack_hand_secondary(user, modifiers) -/obj/machinery/chem_dispenser/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation /obj/machinery/chem_dispenser/drinks name = "soda dispenser" diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm index 857cd5bd221..76b2dbf7f96 100644 --- a/code/modules/reagents/chemistry/machinery/chem_heater.dm +++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm @@ -94,9 +94,9 @@ heater_coefficient *= micro_laser.tier -/obj/machinery/chem_heater/item_interaction(mob/living/user, obj/item/held_item, list/modifiers, is_right_clicking) +/obj/machinery/chem_heater/item_interaction(mob/living/user, obj/item/held_item, list/modifiers) if((held_item.item_flags & ABSTRACT) || (held_item.flags_1 & HOLOGRAM_1)) - return ..() + return NONE if(QDELETED(beaker)) if(istype(held_item, /obj/item/reagent_containers/dropper) || istype(held_item, /obj/item/reagent_containers/syringe)) @@ -110,7 +110,7 @@ balloon_alert(user, "beaker added") return ITEM_INTERACT_SUCCESS - return ..() + return NONE /obj/machinery/chem_heater/wrench_act(mob/living/user, obj/item/tool) . = ITEM_INTERACT_BLOCKING diff --git a/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm b/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm index 298fe259814..ca75736db03 100644 --- a/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm +++ b/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm @@ -147,9 +147,9 @@ 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) +/obj/machinery/chem_mass_spec/item_interaction(mob/living/user, obj/item/item, list/modifiers) if((item.item_flags & ABSTRACT) || (item.flags_1 & HOLOGRAM_1) || !can_interact(user) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) - return ..() + return NONE if(is_reagent_container(item) && item.is_open_container()) if(processing_reagents) @@ -160,13 +160,14 @@ if(!user.transferItemToLoc(beaker, src)) return ITEM_INTERACT_BLOCKING + var/is_right_clicking = LAZYACCESS(modifiers, RIGHT_CLICK) 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 ITEM_INTERACT_SUCCESS - return ..() + return NONE /obj/machinery/chem_mass_spec/wrench_act(mob/living/user, obj/item/tool) . = ITEM_INTERACT_BLOCKING @@ -433,14 +434,12 @@ replace_beaker(ui.user, FALSE) return TRUE -/obj/machinery/chem_mass_spec/AltClick(mob/living/user) - . = ..() - if(!can_interact(user)) - return +/obj/machinery/chem_mass_spec/click_alt(mob/living/user) if(processing_reagents) balloon_alert(user, "still processing!") - return ..() + return CLICK_ACTION_BLOCKING replace_beaker(user, TRUE) + return CLICK_ACTION_SUCCESS /obj/machinery/chem_mass_spec/alt_click_secondary(mob/living/user) . = ..() diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index 092443db8d0..9f210e12ee4 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -1,84 +1,94 @@ -#define TRANSFER_MODE_DESTROY 0 -#define TRANSFER_MODE_MOVE 1 -#define TARGET_BEAKER "beaker" -#define TARGET_BUFFER "buffer" - /obj/machinery/chem_master name = "ChemMaster 3000" desc = "Used to separate chemicals and distribute them in a variety of forms." - density = TRUE - layer = BELOW_OBJ_LAYER icon = 'icons/obj/medical/chemical.dmi' icon_state = "chemmaster" base_icon_state = "chemmaster" + density = TRUE idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.2 + active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.2 resistance_flags = FIRE_PROOF | ACID_PROOF circuit = /obj/item/circuitboard/machine/chem_master - /// Icons for different percentages of buffer reagents - var/fill_icon = 'icons/obj/medical/reagent_fillings.dmi' - var/fill_icon_state = "chemmaster" - var/static/list/fill_icon_thresholds = list(10, 20, 30, 40, 50, 60, 70, 80, 90, 100) + /// Inserted reagent container var/obj/item/reagent_containers/beaker /// Whether separated reagents should be moved back to container or destroyed. - var/transfer_mode = TRANSFER_MODE_MOVE - /// Whether reagent analysis screen is active - var/reagent_analysis_mode = FALSE - /// Reagent being analyzed - var/datum/reagent/analyzed_reagent + var/is_transfering = TRUE /// List of printable container types - var/list/printable_containers = list() - /// Container used by default to reset to (REF) - var/default_container - /// Selected printable container type (REF) - var/selected_container - /// Whether the machine has an option to suggest container - var/has_container_suggestion = FALSE - /// Whether to suggest container or not - var/do_suggest_container = FALSE - /// The container suggested by main reagent in the buffer - var/suggested_container + var/list/printable_containers + /// Container used by default to reset to + var/obj/item/reagent_containers/default_container + /// Selected printable container type + var/obj/item/reagent_containers/selected_container /// Whether the machine is busy with printing containers var/is_printing = FALSE - /// Number of printed containers in the current printing cycle for UI progress bar + /// Number of containers printed so far var/printing_progress + /// Number of containers to be printed var/printing_total - /// Default duration of printing cycle - var/printing_speed = 0.75 SECONDS // Duration of animation - /// The amount of containers printed in one cycle + /// The amount of containers that can be printed in 1 cycle var/printing_amount = 1 /obj/machinery/chem_master/Initialize(mapload) create_reagents(100) - load_printable_containers() - default_container = REF(printable_containers[printable_containers[1]][1]) + + printable_containers = load_printable_containers() + default_container = printable_containers[printable_containers[1]][1] selected_container = default_container - return ..() + + register_context() + + . = ..() + + var/obj/item/circuitboard/machine/chem_master/board = circuit + board.build_path = type + board.name = name /obj/machinery/chem_master/Destroy() QDEL_NULL(beaker) return ..() -/obj/machinery/chem_master/on_deconstruction(disassembled) - replace_beaker() - return ..() +/obj/machinery/chem_master/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)) + if(isnull(held_item)) + context[SCREENTIP_CONTEXT_RMB] = "Remove beaker" + . = CONTEXTUAL_SCREENTIP_SET + return . -/obj/machinery/chem_master/Exited(atom/movable/gone, direction) + if(is_reagent_container(held_item) && held_item.is_open_container()) + if(!QDELETED(beaker)) + context[SCREENTIP_CONTEXT_LMB] = "Replace beaker" + else + context[SCREENTIP_CONTEXT_LMB] = "Insert beaker" + return CONTEXTUAL_SCREENTIP_SET + + if(held_item.tool_behaviour == TOOL_SCREWDRIVER) + context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] panel" + 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(panel_open && held_item.tool_behaviour == TOOL_CROWBAR) + context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" + return CONTEXTUAL_SCREENTIP_SET + +/obj/machinery/chem_master/examine(mob/user) . = ..() - if(gone == beaker) - beaker = null - update_appearance(UPDATE_ICON) + if(in_range(user, src) || isobserver(user)) + . += span_notice("The status display reads:
    Reagent buffer capacity: [reagents.maximum_volume] units.
    Number of containers printed per cycle [printing_amount].") + if(!QDELETED(beaker)) + . += span_notice("[beaker] of [beaker.reagents.maximum_volume]u capacity inserted") + . += span_notice("Right click with empty hand to remove beaker") + else + . += span_warning("Missing input beaker") -/obj/machinery/chem_master/RefreshParts() - . = ..() - reagents.maximum_volume = 0 - for(var/obj/item/reagent_containers/cup/beaker/beaker in component_parts) - reagents.maximum_volume += beaker.reagents.maximum_volume - printing_amount = 0 - for(var/datum/stock_part/servo/servo in component_parts) - printing_amount += servo.tier + . += span_notice("It can be [EXAMINE_HINT("wrenched")] [anchored ? "loose" : "in place"]") + . += span_notice("Its maintainence panel can be [EXAMINE_HINT("screwed")] [panel_open ? "close" : "open"]") + if(panel_open) + . += span_notice("The machine can be [EXAMINE_HINT("pried")] apart.") -/obj/machinery/chem_master/update_appearance(updates=ALL) +/obj/machinery/chem_master/update_appearance(updates) . = ..() if(panel_open || (machine_stat & (NOPOWER|BROKEN))) set_light(0) @@ -102,9 +112,7 @@ // Screen overlay if(!panel_open && !(machine_stat & (NOPOWER | BROKEN))) var/screen_overlay = base_icon_state + "_overlay_screen" - if(reagent_analysis_mode) - screen_overlay += "_analysis" - else if(is_printing) + if(is_printing) screen_overlay += "_active" else if(reagents.total_volume > 0) screen_overlay += "_main" @@ -114,46 +122,130 @@ // Buffer reagents overlay if(reagents.total_volume) var/threshold = null + var/static/list/fill_icon_thresholds = list(10, 20, 30, 40, 50, 60, 70, 80, 90, 100) for(var/i in 1 to fill_icon_thresholds.len) - if(ROUND_UP(100 * reagents.total_volume / reagents.maximum_volume) >= fill_icon_thresholds[i]) + if(ROUND_UP(100 * (reagents.total_volume / reagents.maximum_volume)) >= fill_icon_thresholds[i]) threshold = i if(threshold) - var/fill_name = "[fill_icon_state][fill_icon_thresholds[threshold]]" - var/mutable_appearance/filling = mutable_appearance(fill_icon, fill_name) + var/fill_name = "chemmaster[fill_icon_thresholds[threshold]]" + var/mutable_appearance/filling = mutable_appearance('icons/obj/medical/reagent_fillings.dmi', fill_name) filling.color = mix_color_from_reagents(reagents.reagent_list) . += filling -/obj/machinery/chem_master/wrench_act(mob/living/user, obj/item/tool) +/obj/machinery/chem_master/wrench_act(mob/living/user, obj/item/tool) //SKYRAT ADDITION START if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN) return ITEM_INTERACT_SUCCESS - return ITEM_INTERACT_BLOCKING + return ITEM_INTERACT_BLOCKING //SKYRAT ADDITION END -/obj/machinery/chem_master/screwdriver_act(mob/living/user, obj/item/tool) - if(default_deconstruction_screwdriver(user, icon_state, icon_state, tool)) - update_appearance(UPDATE_ICON) - return ITEM_INTERACT_SUCCESS - return ITEM_INTERACT_BLOCKING +/obj/machinery/chem_master/Exited(atom/movable/gone, direction) + . = ..() + if(gone == beaker) + beaker = null + update_appearance(UPDATE_OVERLAYS) -/obj/machinery/chem_master/crowbar_act(mob/living/user, obj/item/tool) - if(default_deconstruction_crowbar(tool)) - return ITEM_INTERACT_SUCCESS - return ITEM_INTERACT_BLOCKING +/obj/machinery/chem_master/on_set_is_operational(old_value) + if(!is_operational) + is_printing = FALSE + update_appearance(UPDATE_OVERLAYS) -/obj/machinery/chem_master/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) - if(is_reagent_container(tool) && !(tool.item_flags & ABSTRACT) && tool.is_open_container()) +/obj/machinery/chem_master/RefreshParts() + . = ..() + reagents.maximum_volume = 0 + for(var/obj/item/reagent_containers/cup/beaker/beaker in component_parts) + reagents.maximum_volume += beaker.reagents.maximum_volume + + printing_amount = 0 + for(var/datum/stock_part/servo/servo in component_parts) + printing_amount += servo.tier * 12.5 + printing_amount = min(50, ROUND_UP(printing_amount)) + +///Return a map of category->list of containers this machine can print +/obj/machinery/chem_master/proc/load_printable_containers() + PROTECTED_PROC(TRUE) + SHOULD_BE_PURE(TRUE) + + var/static/list/containers + if(!length(containers)) + containers = list( + CAT_TUBES = GLOB.reagent_containers[CAT_TUBES], + CAT_PILLS = GLOB.reagent_containers[CAT_PILLS], + CAT_PATCHES = GLOB.reagent_containers[CAT_PATCHES], + ) + return containers + +/obj/machinery/chem_master/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(user.combat_mode || (tool.item_flags & ABSTRACT) || (tool.flags_1 & HOLOGRAM_1) || !can_interact(user) || !user.can_perform_action(src, ALLOW_SILICON_REACH | FORBID_TELEKINESIS_REACH)) + return NONE + + if(is_reagent_container(tool) && tool.is_open_container()) replace_beaker(user, tool) if(!panel_open) ui_interact(user) + return ITEM_INTERACT_SUCCESS + else + return ITEM_INTERACT_BLOCKING + + return NONE + +/obj/machinery/chem_master/wrench_act(mob/living/user, obj/item/tool) + if(user.combat_mode) + return NONE + + . = ITEM_INTERACT_BLOCKING + if(is_printing) + balloon_alert(user, "still printing!") + return . + + if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN) return ITEM_INTERACT_SUCCESS - return ..() +/obj/machinery/chem_master/screwdriver_act(mob/living/user, obj/item/tool) + if(user.combat_mode) + return NONE + + . = ITEM_INTERACT_BLOCKING + if(is_printing) + balloon_alert(user, "still printing!") + return . + + if(default_deconstruction_screwdriver(user, icon_state, icon_state, tool)) + update_appearance(UPDATE_OVERLAYS) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/chem_master/crowbar_act(mob/living/user, obj/item/tool) + if(user.combat_mode) + return NONE + + . = ITEM_INTERACT_BLOCKING + if(is_printing) + balloon_alert(user, "still printing!") + return . + + if(default_deconstruction_crowbar(tool)) + return ITEM_INTERACT_SUCCESS + +/** + * Insert, remove, replace the existig beaker + * Arguments + * + * * mob/living/user - the player trying to replace the beaker + * * obj/item/reagent_containers/new_beaker - the beaker we are trying to insert, swap with existing or remove if null + */ +/obj/machinery/chem_master/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker) + PRIVATE_PROC(TRUE) + + if(!QDELETED(beaker)) + try_put_in_hand(beaker, user) + if(!QDELETED(new_beaker) && user.transferItemToLoc(new_beaker, src)) + beaker = new_beaker + update_appearance(UPDATE_OVERLAYS) /obj/machinery/chem_master/attack_hand_secondary(mob/user, list/modifiers) . = ..() if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) return . - if(!can_interact(user) || !user.can_perform_action(src, ALLOW_SILICON_REACH|FORBID_TELEKINESIS_REACH)) + if(!can_interact(user) || !user.can_perform_action(src, ALLOW_SILICON_REACH | FORBID_TELEKINESIS_REACH)) return . replace_beaker(user) return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN @@ -164,27 +256,6 @@ /obj/machinery/chem_master/attack_ai_secondary(mob/user, list/modifiers) return attack_hand_secondary(user, modifiers) -/// Insert new beaker and/or eject the inserted one -/obj/machinery/chem_master/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker) - if(new_beaker && user && !user.transferItemToLoc(new_beaker, src)) - return FALSE - if(beaker) - try_put_in_hand(beaker, user) - beaker = null - if(new_beaker) - beaker = new_beaker - update_appearance(UPDATE_ICON) - return TRUE - -/obj/machinery/chem_master/proc/load_printable_containers() - printable_containers = list( - CAT_TUBES = GLOB.reagent_containers[CAT_TUBES], - CAT_PILLS = GLOB.reagent_containers[CAT_PILLS], - CAT_PATCHES = GLOB.reagent_containers[CAT_PATCHES], - CAT_HYPOS = GLOB.reagent_containers[CAT_HYPOS], // SKYRAT EDIT ADDITION - CAT_DARTS = GLOB.reagent_containers[CAT_DARTS], // SKYRAT EDIT ADDITION - ) - /obj/machinery/chem_master/ui_assets(mob/user) return list( get_asset_datum(/datum/asset/spritesheet/chemmaster) @@ -198,269 +269,284 @@ /obj/machinery/chem_master/ui_static_data(mob/user) var/list/data = list() + data["categories"] = list() for(var/category in printable_containers) - var/container_data = list() + //make the category + var/list/category_list = list( + "name" = category, + "containers" = list(), + ) + + //add containers to this category for(var/obj/item/reagent_containers/container as anything in printable_containers[category]) - container_data += list(list( + category_list["containers"] += list(list( "icon" = sanitize_css_class_name("[container]"), "ref" = REF(container), "name" = initial(container.name), "volume" = initial(container.volume), )) - data["categories"]+= list(list( - "name" = category, - "containers" = container_data, - )) + + //add the category + data["categories"] += list(category_list) return data /obj/machinery/chem_master/ui_data(mob/user) - var/list/data = list() + . = list() - data["reagentAnalysisMode"] = reagent_analysis_mode - if(reagent_analysis_mode && analyzed_reagent) - var/state - switch(analyzed_reagent.reagent_state) - if(SOLID) - state = "Solid" - if(LIQUID) - state = "Liquid" - if(GAS) - state = "Gas" - else - state = "Unknown" - data["analysisData"] = list( - "name" = analyzed_reagent.name, - "state" = state, - "pH" = analyzed_reagent.ph, - "color" = analyzed_reagent.color, - "description" = analyzed_reagent.description, - "purity" = analyzed_reagent.purity, - "metaRate" = analyzed_reagent.metabolization_rate, - "overdose" = analyzed_reagent.overdose_threshold, - "addictionTypes" = reagents.parse_addictions(analyzed_reagent), - ) - else - data["isPrinting"] = is_printing - data["printingProgress"] = printing_progress - data["printingTotal"] = printing_total - data["hasBeaker"] = beaker ? TRUE : FALSE - data["beakerCurrentVolume"] = beaker ? round(beaker.reagents.total_volume, 0.01) : null - data["beakerMaxVolume"] = beaker ? beaker.volume : null - var/list/beaker_contents = list() - if(beaker) - for(var/datum/reagent/reagent in beaker.reagents.reagent_list) - beaker_contents.Add(list(list("name" = reagent.name, "ref" = REF(reagent), "volume" = round(reagent.volume, 0.01)))) - data["beakerContents"] = beaker_contents + //printing statictics + .["isPrinting"] = is_printing + .["printingProgress"] = printing_progress + .["printingTotal"] = printing_total + .["maxPrintable"] = printing_amount - var/list/buffer_contents = list() - if(reagents.total_volume) - for(var/datum/reagent/reagent in reagents.reagent_list) - buffer_contents.Add(list(list("name" = reagent.name, "ref" = REF(reagent), "volume" = round(reagent.volume, 0.01)))) - data["bufferContents"] = buffer_contents - data["bufferCurrentVolume"] = round(reagents.total_volume, 0.01) - data["bufferMaxVolume"] = reagents.maximum_volume + //contents of source beaker + var/list/beaker_data = null + if(!QDELETED(beaker)) + beaker_data = list() + beaker_data["maxVolume"] = beaker.volume + 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 as anything in beaker.reagents.reagent_list) + beakerContents += list(list( + "ref" = "[reagent.type]", + "name" = reagent.name, + "volume" = round(reagent.volume, CHEMICAL_VOLUME_ROUNDING), + "pH" = reagent.ph, + "color" = reagent.color, + "description" = reagent.description, + "purity" = reagent.purity, + "metaRate" = reagent.metabolization_rate, + "overdose" = reagent.overdose_threshold, + "addictionTypes" = reagents.parse_addictions(reagent), + )) + beaker_data["contents"] = beakerContents + .["beaker"] = beaker_data - data["transferMode"] = transfer_mode + //contents of buffer + beaker_data = list() + beaker_data["maxVolume"] = reagents.maximum_volume + beaker_data["currentVolume"] = round(reagents.total_volume, CHEMICAL_VOLUME_ROUNDING) + var/list/beakerContents = list() + if(length(reagents.reagent_list)) + for(var/datum/reagent/reagent as anything in reagents.reagent_list) + beakerContents += list(list( + "ref" = "[reagent.type]", + "name" = reagent.name, + "volume" = round(reagent.volume, CHEMICAL_VOLUME_ROUNDING), + "pH" = reagent.ph, + "color" = reagent.color, + "description" = reagent.description, + "purity" = reagent.purity, + "metaRate" = reagent.metabolization_rate, + "overdose" = reagent.overdose_threshold, + "addictionTypes" = reagents.parse_addictions(reagent), + )) + beaker_data["contents"] = beakerContents + .["buffer"] = beaker_data - data["hasContainerSuggestion"] = !!has_container_suggestion - if(has_container_suggestion) - data["doSuggestContainer"] = !!do_suggest_container - if(do_suggest_container) - if(reagents.total_volume > 0) - var/master_reagent = reagents.get_master_reagent() - suggested_container = get_suggested_container(master_reagent) - else - suggested_container = default_container - data["suggestedContainer"] = suggested_container - selected_container = suggested_container - else if (isnull(selected_container)) - selected_container = default_container + //is transfering or destroying reagents. applied only for buffer + .["isTransfering"] = is_transfering - data["selectedContainerRef"] = selected_container - var/obj/item/reagent_containers/container = locate(selected_container) - data["selectedContainerVolume"] = initial(container.volume) + //container along with the suggested type + var/obj/item/reagent_containers/suggested_container = default_container + if(reagents.total_volume > 0) + var/datum/reagent/master_reagent = reagents.get_master_reagent() + var/container_found = FALSE + suggested_container = master_reagent.default_container + for(var/category in printable_containers) + for(var/obj/item/reagent_containers/container as anything in printable_containers[category]) + if(container == suggested_container) + suggested_container = REF(container) + container_found = TRUE + break + if(!container_found) + suggested_container = REF(default_container) + .["suggestedContainerRef"] = suggested_container - return data + //selected container + .["selectedContainerRef"] = REF(selected_container) + .["selectedContainerVolume"] = initial(selected_container.volume) -/obj/machinery/chem_master/ui_act(action, params) +/** + * Transfers a single reagent between buffer & beaker + * Arguments + * + * * mob/user - the player who is attempting the transfer + * * datum/reagents/source - the holder we are transferring from + * * datum/reagents/target - the holder we are transferring to + * * datum/reagent/path - the reagent typepath we are transfering + * * amount - volume to transfer -1 means custom amount + * * do_transfer - transfer the reagents else destroy them + */ +/obj/machinery/chem_master/proc/transfer_reagent(mob/user, datum/reagents/source, datum/reagents/target, datum/reagent/path, amount, do_transfer) + PRIVATE_PROC(TRUE) + + //sanity checks for transfer amount + if(isnull(amount)) + return FALSE + amount = text2num(amount) + if(isnull(amount)) + return FALSE + if(amount == -1) + var/target_amount = tgui_input_number(user, "Enter amount to transfer", "Transfer amount") + if(!target_amount) + return FALSE + amount = text2num(target_amount) + if(isnull(amount)) + return FALSE + if(amount <= 0) + return FALSE + + //sanity checks for reagent path + var/datum/reagent/reagent = text2path(path) + if (!reagent) + return FALSE + + //use energy + if(!use_energy(active_power_usage, force = FALSE)) + return FALSE + + //do the operation + . = FALSE + if(do_transfer) + if(target.is_reacting) + return FALSE + if(source.trans_to(target, amount, target_id = reagent)) + . = TRUE + else if(source.remove_reagent(reagent, amount)) + . = TRUE + if(. && !QDELETED(src)) //transferring volatile reagents can cause a explosion & destory us + update_appearance(UPDATE_OVERLAYS) + return . + +/obj/machinery/chem_master/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() if(.) return - if(action == "eject") - replace_beaker(usr) - return TRUE - - if(action == "transfer") - var/reagent_ref = params["reagentRef"] - var/amount = text2num(params["amount"]) - var/target = params["target"] - return transfer_reagent(reagent_ref, amount, target) - - if(action == "toggleTransferMode") - transfer_mode = !transfer_mode - return TRUE - - if(action == "analyze") - analyzed_reagent = locate(params["reagentRef"]) - if(analyzed_reagent) - reagent_analysis_mode = TRUE - update_appearance(UPDATE_ICON) + switch(action) + if("eject") + replace_beaker(ui.user) return TRUE - if(action == "stopAnalysis") - reagent_analysis_mode = FALSE - analyzed_reagent = null - update_appearance(UPDATE_ICON) - return TRUE + if("transfer") + if(is_printing) + say("buffer locked while printing!") + return - if(action == "stopPrinting") + var/reagent_ref = params["reagentRef"] + var/amount = params["amount"] + var/target = params["target"] + + if(target == "buffer") + return transfer_reagent(ui.user, beaker.reagents, reagents, reagent_ref, amount, TRUE) + else if(target == "beaker") + return transfer_reagent(ui.user, reagents, beaker.reagents, reagent_ref, amount, is_transfering) + return FALSE + + if("toggleTransferMode") + is_transfering = !is_transfering + return TRUE + + if("stopPrinting") + is_printing = FALSE + update_appearance(UPDATE_OVERLAYS) + return TRUE + + if("selectContainer") + var/obj/item/reagent_containers/target = locate(params["ref"]) + if(!ispath(target)) + return FALSE + + selected_container = target + return TRUE + + if("create") + if(!reagents.total_volume || is_printing) + return FALSE + + //validate print count + var/item_count = params["itemCount"] + if(isnull(item_count)) + return FALSE + item_count = text2num(item_count) + if(isnull(item_count) || item_count <= 0) + return FALSE + item_count = min(item_count, printing_amount) + var/volume_in_each = round(reagents.total_volume / item_count, CHEMICAL_VOLUME_ROUNDING) + + // Generate item name + var/item_name_default = initial(selected_container.name) + var/datum/reagent/master_reagent = reagents.get_master_reagent() + if(selected_container == default_container) // Tubes and bottles gain reagent name + item_name_default = "[master_reagent.name] [item_name_default]" + if(!(initial(selected_container.reagent_flags) & OPENCONTAINER)) // Closed containers get both reagent name and units in the name + item_name_default = "[master_reagent.name] [item_name_default] ([volume_in_each]u)" + var/item_name = tgui_input_text(usr, + "Container name", + "Name", + item_name_default, + MAX_NAME_LEN) + if(!item_name) + return FALSE + + //start printing + is_printing = TRUE + printing_progress = 0 + printing_total = item_count + update_appearance(UPDATE_OVERLAYS) + create_containers(ui.user, item_count, item_name, volume_in_each) + return TRUE + +/** + * Create N selected containers with reagents from buffer split between them + * Arguments + * + * * mob/user - the player printing these containers + * * item_count - number of containers to print + * * item_name - the name for each container printed + * * volume_in_each - volume in each container created + */ +/obj/machinery/chem_master/proc/create_containers(mob/user, item_count, item_name, volume_in_each) + PRIVATE_PROC(TRUE) + + //lost power or manually stopped + if(!is_printing) + return + + //use power + if(!use_energy(active_power_usage, force = FALSE)) is_printing = FALSE - return TRUE + update_appearance(UPDATE_OVERLAYS) + return - if(action == "toggleContainerSuggestion") - do_suggest_container = !do_suggest_container - return TRUE + //print the stuff + var/obj/item/reagent_containers/item = new selected_container(drop_location()) + adjust_item_drop_location(item) + item.name = item_name + item.reagents.clear_reagents() + reagents.trans_to(item, volume_in_each, transferred_by = user) + printing_progress++ + update_appearance(UPDATE_OVERLAYS) - if(action == "selectContainer") - selected_container = params["ref"] - return TRUE - - if(action == "create") - if(reagents.total_volume == 0) - return FALSE - var/item_count = text2num(params["itemCount"]) - if(item_count <= 0) - return FALSE - create_containers(item_count) - return TRUE - -/// Create N selected containers with reagents from buffer split between them -/obj/machinery/chem_master/proc/create_containers(item_count = 1) - var/obj/item/reagent_containers/container_style = locate(selected_container) - var/is_pill_subtype = ispath(container_style, /obj/item/reagent_containers/pill) - var/volume_in_each = reagents.total_volume / item_count - var/printing_amount_current = is_pill_subtype ? printing_amount * 2 : printing_amount - - // Generate item name - var/item_name_default = initial(container_style.name) - var/datum/reagent/master_reagent = reagents.get_master_reagent() - if(selected_container == default_container) // Tubes and bottles gain reagent name - item_name_default = "[master_reagent.name] [item_name_default]" - if(!(initial(container_style.reagent_flags) & OPENCONTAINER)) // Closed containers get both reagent name and units in the name - item_name_default = "[master_reagent.name] [item_name_default] ([volume_in_each]u)" - var/item_name = tgui_input_text(usr, - "Container name", - "Name", - item_name_default, - MAX_NAME_LEN) - - if(!item_name || !reagents.total_volume || QDELETED(src) || !usr.can_perform_action(src, ALLOW_SILICON_REACH)) - return FALSE - - // Print and fill containers - is_printing = TRUE - update_appearance(UPDATE_ICON) - printing_progress = 0 - printing_total = item_count - while(item_count > 0) - if(!is_printing) - break - use_energy(active_power_usage) - stoplag(printing_speed) - for(var/i in 1 to printing_amount_current) - if(!item_count) - continue - var/obj/item/reagent_containers/item = new container_style(drop_location()) - adjust_item_drop_location(item) - item.name = item_name - item.reagents.clear_reagents() - reagents.trans_to(item, volume_in_each, transferred_by = src) - printing_progress++ - item_count-- - update_appearance(UPDATE_ICON) - is_printing = FALSE - update_appearance(UPDATE_ICON) - return TRUE - -/// Transfer reagents to specified target from the opposite source -/obj/machinery/chem_master/proc/transfer_reagent(reagent_ref, amount, target) - if (amount == -1) - amount = text2num(input("Enter the amount you want to transfer:", name, "")) - if (amount == null || amount <= 0) - return FALSE - if (!beaker && target == TARGET_BEAKER && transfer_mode == TRANSFER_MODE_MOVE) - return FALSE - var/datum/reagent/reagent = locate(reagent_ref) - if (!reagent) - return FALSE - - use_energy(active_power_usage) - - if (target == TARGET_BUFFER) - if(!check_reactions(reagent, beaker.reagents)) - return FALSE - beaker.reagents.trans_to(src, amount, target_id = reagent.type) - update_appearance(UPDATE_ICON) - return TRUE - - if (target == TARGET_BEAKER && transfer_mode == TRANSFER_MODE_DESTROY) - reagents.remove_reagent(reagent.type, amount) - update_appearance(UPDATE_ICON) - return TRUE - if (target == TARGET_BEAKER && transfer_mode == TRANSFER_MODE_MOVE) - if(!check_reactions(reagent, reagents)) - return FALSE - reagents.trans_to(beaker, amount, target_id = reagent.type) - update_appearance(UPDATE_ICON) - return TRUE - - return FALSE - -/// Checks to see if the target reagent is being created (reacting) and if so prevents transfer -/// Only prevents reactant from being moved so that people can still manlipulate input reagents -/obj/machinery/chem_master/proc/check_reactions(datum/reagent/reagent, datum/reagents/holder) - if(!reagent) - return FALSE - var/canMove = TRUE - for(var/datum/equilibrium/equilibrium as anything in holder.reaction_list) - if(equilibrium.reaction.reaction_flags & REACTION_COMPETITIVE) - continue - for(var/datum/reagent/result as anything in equilibrium.reaction.required_reagents) - if(result == reagent.type) - canMove = FALSE - if(!canMove) - say("Cannot move reagent during reaction!") - return canMove - -/// Retrieve REF to the best container for provided reagent -/obj/machinery/chem_master/proc/get_suggested_container(datum/reagent/reagent) - var/preferred_container = reagent.default_container - for(var/category in printable_containers) - for(var/container in printable_containers[category]) - if(container == preferred_container) - return REF(container) - return default_container - -/obj/machinery/chem_master/examine(mob/user) - . = ..() - if(in_range(user, src) || isobserver(user)) - . += span_notice("The status display reads:
    Reagent buffer capacity: [reagents.maximum_volume] units.
    Number of containers printed at once increased by [100 * (printing_amount / initial(printing_amount)) - 100]%.") + //print more items + item_count -- + if(item_count > 0) + addtimer(CALLBACK(src, PROC_REF(create_containers), user, item_count, item_name, volume_in_each), 0.75 SECONDS) + else + is_printing = FALSE + update_appearance(UPDATE_OVERLAYS) /obj/machinery/chem_master/condimaster name = "CondiMaster 3000" desc = "Used to create condiments and other cooking supplies." icon_state = "condimaster" - has_container_suggestion = TRUE /obj/machinery/chem_master/condimaster/load_printable_containers() - printable_containers = list( - CAT_CONDIMENTS = GLOB.reagent_containers[CAT_CONDIMENTS], - ) - -#undef TRANSFER_MODE_DESTROY -#undef TRANSFER_MODE_MOVE -#undef TARGET_BEAKER -#undef TARGET_BUFFER + var/static/list/containers + if(!length(containers)) + containers = list(CAT_CONDIMENTS = GLOB.reagent_containers[CAT_CONDIMENTS]) + return containers diff --git a/code/modules/reagents/chemistry/machinery/chem_synthesizer.dm b/code/modules/reagents/chemistry/machinery/chem_synthesizer.dm index c0cb45dda2a..552bfe48650 100644 --- a/code/modules/reagents/chemistry/machinery/chem_synthesizer.dm +++ b/code/modules/reagents/chemistry/machinery/chem_synthesizer.dm @@ -6,14 +6,16 @@ base_icon_state = "dispenser" amount = 10 resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | LAVA_PROOF - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION use_power = NO_POWER_USE - var/static/list/shortcuts = list( - "meth" = /datum/reagent/drug/methamphetamine - ) ///The purity of the created reagent in % (purity uses 0-1 values) var/purity = 100 +/obj/machinery/chem_dispenser/chem_synthesizer/screwdriver_act(mob/living/user, obj/item/tool) + return NONE + +/obj/machinery/chem_dispenser/chem_synthesizer/crowbar_act(mob/living/user, obj/item/tool) + return NONE + /obj/machinery/chem_dispenser/chem_synthesizer/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/portable_chem_mixer.dm b/code/modules/reagents/chemistry/machinery/portable_chem_mixer.dm index a6113d2f0c6..25a7eecbd37 100644 --- a/code/modules/reagents/chemistry/machinery/portable_chem_mixer.dm +++ b/code/modules/reagents/chemistry/machinery/portable_chem_mixer.dm @@ -9,6 +9,7 @@ slot_flags = ITEM_SLOT_BELT custom_price = PAYCHECK_CREW * 10 custom_premium_price = PAYCHECK_CREW * 14 + interaction_flags_click = FORBID_TELEKINESIS_REACH ///Creating an empty slot for a beaker that can be added to dispense into var/obj/item/reagent_containers/beaker @@ -105,14 +106,14 @@ /obj/item/storage/portable_chem_mixer/ex_act(severity, target) return severity > EXPLODE_LIGHT ? ..() : FALSE -/obj/item/storage/portable_chem_mixer/item_interaction(mob/living/user, obj/item/weapon, list/modifiers, is_right_clicking) +/obj/item/storage/portable_chem_mixer/item_interaction(mob/living/user, obj/item/weapon, list/modifiers) if (!atom_storage.locked || \ (weapon.item_flags & ABSTRACT) || \ (weapon.flags_1 & HOLOGRAM_1) || \ !is_reagent_container(weapon) || \ !weapon.is_open_container() \ ) - return ..() + return NONE replace_beaker(user, weapon) update_appearance() @@ -250,15 +251,14 @@ var/atom/movable/screen/inventory/hand/H = over_object M.putItemFromInventoryInHandIfPossible(src, H.held_index) -/obj/item/storage/portable_chem_mixer/AltClick(mob/living/user) +/obj/item/storage/portable_chem_mixer/click_alt(mob/living/user) if(!atom_storage.locked) balloon_alert(user, "lock first to use alt eject!") - return ..() - if(!can_interact(user) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) - return + return CLICK_ACTION_BLOCKING replace_beaker(user) update_appearance() + return CLICK_ACTION_SUCCESS /obj/item/storage/portable_chem_mixer/CtrlClick(mob/living/user) if(atom_storage.locked == STORAGE_FULLY_LOCKED) diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm index bdd4f125075..e206ffebbc9 100644 --- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm +++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm @@ -99,7 +99,12 @@ . += span_notice("Filled to [round((total_weight / maximum_weight) * 100)]% capacity.") if(!QDELETED(beaker)) - . += span_notice("A beaker of [beaker.reagents.maximum_volume]u capacity is present.") + . += span_notice("A beaker of [beaker.reagents.maximum_volume]u capacity is present. Contains:") + if(beaker.reagents.total_volume) + for(var/datum/reagent/reg as anything in beaker.reagents.reagent_list) + . += span_notice("[round(reg.volume, CHEMICAL_VOLUME_ROUNDING)]u of [reg.name]") + else + . += span_notice("Nothing.") . += span_notice("[EXAMINE_HINT("Right click")] with empty hand to remove beaker.") else . += span_warning("It's missing a beaker.") @@ -206,9 +211,9 @@ return items_transfered -/obj/machinery/reagentgrinder/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) +/obj/machinery/reagentgrinder/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(user.combat_mode || (tool.item_flags & ABSTRACT) || (tool.flags_1 & HOLOGRAM_1) || !can_interact(user) || !user.can_perform_action(src, ALLOW_SILICON_REACH)) - return ..() + return NONE //add the beaker if (is_reagent_container(tool) && tool.is_open_container()) @@ -257,7 +262,7 @@ to_chat(user, span_warning("You must drag & dump contents of [tool] into [src].")) return ITEM_INTERACT_BLOCKING - return ..() + return NONE /obj/machinery/reagentgrinder/wrench_act(mob/living/user, obj/item/tool) if(user.combat_mode) diff --git a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm index 17b3f236e95..f6e5f74c9bc 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm @@ -1658,7 +1658,7 @@ need_mob_update += drinker.adjustStaminaLoss(-heal_amt, updating_stamina = FALSE, required_biotype = affected_biotype) if(need_mob_update) drinker.updatehealth() - drinker.visible_message(span_warning("[drinker] shivers with renewed vigor!"), span_notice("One taste of [lowertext(name)] fills you with energy!")) + drinker.visible_message(span_warning("[drinker] shivers with renewed vigor!"), span_notice("One taste of [LOWER_TEXT(name)] fills you with energy!")) if(!drinker.stat && heal_points == 20) //brought us out of softcrit drinker.visible_message(span_danger("[drinker] lurches to [drinker.p_their()] feet!"), span_boldnotice("Up and at 'em, kid.")) diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index 90bd7e14a86..a072166ab86 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -488,13 +488,13 @@ adjust_blood_flow(-0.06 * reac_volume, initial_flow * 0.6) // 20u of a salt shacker * 0.1 = -1.6~ blood flow, but is always clamped to, at best, third blood loss from that wound. // Crystal irritation worsening recovery. gauzed_clot_rate *= 0.65 - to_chat(carbies, span_notice("The salt bits seep in and stick to [lowertext(src)], painfully irritating the skin but soaking up most of the blood.")) + to_chat(carbies, span_notice("The salt bits seep in and stick to [LOWER_TEXT(src)], painfully irritating the skin but soaking up most of the blood.")) /datum/wound/slash/flesh/on_salt(reac_volume, mob/living/carbon/carbies) adjust_blood_flow(-0.1 * reac_volume, initial_flow * 0.5) // 20u of a salt shacker * 0.1 = -2~ blood flow, but is always clamped to, at best, halve blood loss from that wound. // Crystal irritation worsening recovery. clot_rate *= 0.75 - to_chat(carbies, span_notice("The salt bits seep in and stick to [lowertext(src)], painfully irritating the skin but soaking up most of the blood.")) + to_chat(carbies, span_notice("The salt bits seep in and stick to [LOWER_TEXT(src)], painfully irritating the skin but soaking up most of the blood.")) /datum/wound/burn/flesh/on_salt(reac_volume) // Slightly sanitizes and disinfects, but also increases infestation rate (some bacteria are aided by salt), and decreases flesh healing (can damage the skin from moisture absorption) @@ -502,7 +502,7 @@ infestation -= max(VALUE_PER(0.3, 30) * reac_volume, 0) infestation_rate += VALUE_PER(0.12, 30) * reac_volume flesh_healing -= max(VALUE_PER(5, 30) * reac_volume, 0) - to_chat(victim, span_notice("The salt bits seep in and stick to [lowertext(src)], painfully irritating the skin! After a few moments, it feels marginally better.")) + to_chat(victim, span_notice("The salt bits seep in and stick to [LOWER_TEXT(src)], painfully irritating the skin! After a few moments, it feels marginally better.")) /datum/reagent/consumable/blackpepper name = "Black Pepper" @@ -535,7 +535,10 @@ . = ..() if(isvampire(affected_mob)) //incapacitating but not lethal. Unfortunately, vampires cannot vomit. if(SPT_PROB(min((current_cycle-1)/2, 12.5), seconds_per_tick)) - to_chat(affected_mob, span_danger("You can't get the scent of garlic out of your nose! You can barely think...")) + if(HAS_TRAIT(affected_mob, TRAIT_ANOSMIA)) + to_chat(affected_mob, span_danger("You feel that something is wrong, your strength is leaving you! You can barely think...")) + else + to_chat(affected_mob, span_danger("You can't get the scent of garlic out of your nose! You can barely think...")) affected_mob.Paralyze(10) affected_mob.set_jitter_if_lower(20 SECONDS) else @@ -653,18 +656,18 @@ /datum/wound/pierce/bleed/on_flour(reac_volume, mob/living/carbon/carbies) adjust_blood_flow(-0.015 * reac_volume) // 30u of a flour sack * 0.015 = -0.45~ blood flow, prettay good - to_chat(carbies, span_notice("The flour seeps into [lowertext(src)], painfully drying it up and absorbing some of the blood.")) + to_chat(carbies, span_notice("The flour seeps into [LOWER_TEXT(src)], painfully drying it up and absorbing some of the blood.")) // When some nerd adds infection for wounds, make this increase the infection /datum/wound/slash/flesh/on_flour(reac_volume, mob/living/carbon/carbies) adjust_blood_flow(-0.04 * reac_volume) // 30u of a flour sack * 0.04 = -1.25~ blood flow, pretty good! - to_chat(carbies, span_notice("The flour seeps into [lowertext(src)], painfully drying some of it up and absorbing a little blood.")) + to_chat(carbies, span_notice("The flour seeps into [LOWER_TEXT(src)], painfully drying some of it up and absorbing a little blood.")) // When some nerd adds infection for wounds, make this increase the infection // Don't pour flour onto burn wounds, it increases infection risk! Very unwise. Backed up by REAL info from REAL professionals. // https://www.reuters.com/article/uk-factcheck-flour-burn-idUSKCN26F2N3 /datum/wound/burn/flesh/on_flour(reac_volume) - to_chat(victim, span_notice("The flour seeps into [lowertext(src)], spiking you with intense pain! That probably wasn't a good idea...")) + to_chat(victim, span_notice("The flour seeps into [LOWER_TEXT(src)], spiking you with intense pain! That probably wasn't a good idea...")) sanitization -= min(0, 1) infestation += 0.2 return @@ -759,18 +762,18 @@ /datum/wound/pierce/bleed/on_starch(reac_volume, mob/living/carbon/carbies) adjust_blood_flow(-0.03 * reac_volume) - to_chat(carbies, span_notice("The slimey starch seeps into [lowertext(src)], painfully drying some of it up and absorbing a little blood.")) + to_chat(carbies, span_notice("The slimey starch seeps into [LOWER_TEXT(src)], painfully drying some of it up and absorbing a little blood.")) // When some nerd adds infection for wounds, make this increase the infection return /datum/wound/slash/flesh/on_starch(reac_volume, mob/living/carbon/carbies) adjust_blood_flow(-0.06 * reac_volume) - to_chat(carbies, span_notice("The slimey starch seeps into [lowertext(src)], painfully drying it up and absorbing some of the blood.")) + to_chat(carbies, span_notice("The slimey starch seeps into [LOWER_TEXT(src)], painfully drying it up and absorbing some of the blood.")) // When some nerd adds infection for wounds, make this increase the infection return /datum/wound/burn/flesh/on_starch(reac_volume, mob/living/carbon/carbies) - to_chat(carbies, span_notice("The slimey starch seeps into [lowertext(src)], spiking you with intense pain! That probably wasn't a good idea...")) + to_chat(carbies, span_notice("The slimey starch seeps into [LOWER_TEXT(src)], spiking you with intense pain! That probably wasn't a good idea...")) sanitization -= min(0, 0.5) infestation += 0.1 return diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 6b6af30612c..8c5a513f69e 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -350,18 +350,18 @@ /datum/wound/pierce/bleed/on_saltwater(reac_volume, mob/living/carbon/carbies) adjust_blood_flow(-0.06 * reac_volume, initial_flow * 0.6) - to_chat(carbies, span_notice("The salt water splashes over [lowertext(src)], soaking up the blood.")) + to_chat(carbies, span_notice("The salt water splashes over [LOWER_TEXT(src)], soaking up the blood.")) /datum/wound/slash/flesh/on_saltwater(reac_volume, mob/living/carbon/carbies) adjust_blood_flow(-0.1 * reac_volume, initial_flow * 0.5) - to_chat(carbies, span_notice("The salt water splashes over [lowertext(src)], soaking up the blood.")) + to_chat(carbies, span_notice("The salt water splashes over [LOWER_TEXT(src)], soaking up the blood.")) /datum/wound/burn/flesh/on_saltwater(reac_volume) // Similar but better stats from normal salt. sanitization += VALUE_PER(0.6, 30) * reac_volume infestation -= max(VALUE_PER(0.5, 30) * reac_volume, 0) infestation_rate += VALUE_PER(0.07, 30) * reac_volume - to_chat(victim, span_notice("The salt water splashes over [lowertext(src)], soaking up the... miscellaneous fluids. It feels somewhat better afterwards.")) + to_chat(victim, span_notice("The salt water splashes over [LOWER_TEXT(src)], soaking up the... miscellaneous fluids. It feels somewhat better afterwards.")) return /datum/reagent/water/holywater @@ -737,7 +737,7 @@ //affected_mob.set_species(species_type) //ORIGINAL affected_mob.set_species(species_type, TRUE, FALSE, null, null, null, null, TRUE) //SKYRAT EDIT CHANGE - CUSTOMIZATION holder.del_reagent(type) - to_chat(affected_mob, span_warning("You've become \a [lowertext(initial(species_type.name))]!")) + to_chat(affected_mob, span_warning("You've become \a [LOWER_TEXT(initial(species_type.name))]!")) return /datum/reagent/mutationtoxin/classic //The one from plasma on green slimes diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm index ce13c9c70de..6407ff0fb8b 100644 --- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm +++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm @@ -456,7 +456,7 @@ required_container = /obj/item/slime_extract/cerulean /datum/chemical_reaction/slime/slime_territory/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) - new /obj/item/areaeditor/blueprints/slime(get_turf(holder.my_atom)) + new /obj/item/blueprints/slime(get_turf(holder.my_atom)) ..() //Sepia diff --git a/code/modules/reagents/reagent_containers/chem_pack.dm b/code/modules/reagents/reagent_containers/chem_pack.dm index 3345f1e99ef..98ffa2e596e 100644 --- a/code/modules/reagents/reagent_containers/chem_pack.dm +++ b/code/modules/reagents/reagent_containers/chem_pack.dm @@ -8,23 +8,29 @@ spillable = TRUE obj_flags = UNIQUE_RENAME resistance_flags = ACID_PROOF - var/sealed = FALSE fill_icon_thresholds = list(10, 20, 30, 40, 50, 60, 70, 80, 90, 100) has_variable_transfer_amount = FALSE + interaction_flags_click = NEED_DEXTERITY + /// Whether this has been sealed shut + var/sealed = FALSE -/obj/item/reagent_containers/chem_pack/AltClick(mob/living/user) - if(user.can_perform_action(src, NEED_DEXTERITY) && !sealed) - if(iscarbon(user) && (HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))) - to_chat(user, span_warning("Uh... whoops! You accidentally spill the content of the bag onto yourself.")) - SplashReagents(user) - return +/obj/item/reagent_containers/chem_pack/click_alt(mob/living/user) + if(sealed) + balloon_alert(user, "sealed!") + return CLICK_ACTION_BLOCKING - reagents.flags = NONE - reagent_flags = DRAWABLE | INJECTABLE //To allow for sabotage or ghetto use. - reagents.flags = reagent_flags - spillable = FALSE - sealed = TRUE - to_chat(user, span_notice("You seal the bag.")) + if(iscarbon(user) && (HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))) + to_chat(user, span_warning("Uh... whoops! You accidentally spill the content of the bag onto yourself.")) + SplashReagents(user) + return CLICK_ACTION_BLOCKING + + reagents.flags = NONE + reagent_flags = DRAWABLE | INJECTABLE //To allow for sabotage or ghetto use. + reagents.flags = reagent_flags + spillable = FALSE + sealed = TRUE + balloon_alert(user, "sealed") + return CLICK_ACTION_SUCCESS /obj/item/reagent_containers/chem_pack/examine() . = ..() diff --git a/code/modules/reagents/reagent_containers/cups/_cup.dm b/code/modules/reagents/reagent_containers/cups/_cup.dm index 31948c5cc1e..ea0eaf989dd 100644 --- a/code/modules/reagents/reagent_containers/cups/_cup.dm +++ b/code/modules/reagents/reagent_containers/cups/_cup.dm @@ -23,7 +23,7 @@ . = ..() if(drink_type) var/list/types = bitfield_to_list(drink_type, FOOD_FLAGS) - . += span_notice("It is [lowertext(english_list(types))].") + . += span_notice("It is [LOWER_TEXT(english_list(types))].") /** * Checks if the mob actually liked drinking this cup. @@ -481,11 +481,13 @@ spillable = TRUE var/obj/item/grinded -/obj/item/reagent_containers/cup/mortar/AltClick(mob/user) - if(grinded) - grinded.forceMove(drop_location()) - grinded = null - to_chat(user, span_notice("You eject the item inside.")) +/obj/item/reagent_containers/cup/mortar/click_alt(mob/user) + if(!grinded) + return CLICK_ACTION_BLOCKING + grinded.forceMove(drop_location()) + grinded = null + balloon_alert(user, "ejected") + return CLICK_ACTION_SUCCESS /obj/item/reagent_containers/cup/mortar/attackby(obj/item/I, mob/living/carbon/human/user) ..() diff --git a/code/modules/reagents/reagent_containers/cups/bottle.dm b/code/modules/reagents/reagent_containers/cups/bottle.dm index 1e4466da8c3..75bc79c5a6a 100644 --- a/code/modules/reagents/reagent_containers/cups/bottle.dm +++ b/code/modules/reagents/reagent_containers/cups/bottle.dm @@ -513,7 +513,7 @@ return TRUE -/obj/item/reagent_containers/cup/bottle/syrup_bottle/AltClick(mob/user) +/obj/item/reagent_containers/cup/bottle/syrup_bottle/click_alt(mob/user) cap_on = !cap_on if(!cap_on) icon_state = "syrup_open" @@ -522,7 +522,7 @@ icon_state = "syrup" balloon_alert(user, "put pump cap on") update_icon_state() - return ..() + return CLICK_ACTION_SUCCESS /obj/item/reagent_containers/cup/bottle/syrup_bottle/proc/rename(mob/user, obj/item/writing_instrument) if(!user.can_write(writing_instrument)) diff --git a/code/modules/reagents/reagent_containers/cups/drinkingglass.dm b/code/modules/reagents/reagent_containers/cups/drinkingglass.dm index adcd2ff79fa..7441614682c 100644 --- a/code/modules/reagents/reagent_containers/cups/drinkingglass.dm +++ b/code/modules/reagents/reagent_containers/cups/drinkingglass.dm @@ -35,7 +35,7 @@ /obj/item/reagent_containers/cup/glass/drinkingglass/on_reagent_change(datum/reagents/holder, ...) . = ..() if(!length(reagents.reagent_list)) - REMOVE_TRAIT(src, TRAIT_WAS_RENAMED, PEN_LABEL_TRAIT) //so new drinks can rename the glass + REMOVE_TRAIT(src, TRAIT_WAS_RENAMED, RENAMING_TOOL_LABEL_TRAIT) //so new drinks can rename the glass // Having our icon state change removes fill thresholds /obj/item/reagent_containers/cup/glass/drinkingglass/on_cup_change(datum/glass_style/style) @@ -58,7 +58,7 @@ return REMOVE_TRAIT(src, TRAIT_WAS_RENAMED, SHAKER_LABEL_TRAIT) - REMOVE_TRAIT(src, TRAIT_WAS_RENAMED, PEN_LABEL_TRAIT) + REMOVE_TRAIT(src, TRAIT_WAS_RENAMED, RENAMING_TOOL_LABEL_TRAIT) name = initial(name) desc = initial(desc) update_appearance(UPDATE_NAME | UPDATE_DESC) diff --git a/code/modules/reagents/reagent_containers/cups/drinks.dm b/code/modules/reagents/reagent_containers/cups/drinks.dm index cba2f937da4..5a3ed446f60 100644 --- a/code/modules/reagents/reagent_containers/cups/drinks.dm +++ b/code/modules/reagents/reagent_containers/cups/drinks.dm @@ -122,10 +122,10 @@ . += span_notice("Alt-click to toggle cup lid.") return -/obj/item/reagent_containers/cup/glass/coffee/AltClick(mob/user) +/obj/item/reagent_containers/cup/glass/coffee/click_alt(mob/user) lid_open = !lid_open update_icon_state() - return ..() + return CLICK_ACTION_SUCCESS /obj/item/reagent_containers/cup/glass/coffee/update_icon_state() if(lid_open) @@ -248,11 +248,10 @@ else . += span_notice("The cap has been taken off. Alt-click to put a cap on.") -/obj/item/reagent_containers/cup/glass/waterbottle/AltClick(mob/user) - . = ..() +/obj/item/reagent_containers/cup/glass/waterbottle/click_alt(mob/user) if(cap_lost) to_chat(user, span_warning("The cap seems to be missing! Where did it go?")) - return + return CLICK_ACTION_BLOCKING var/fumbled = HAS_TRAIT(user, TRAIT_CLUMSY) && prob(5) if(cap_on || fumbled) @@ -270,6 +269,7 @@ spillable = FALSE to_chat(user, span_notice("You put the cap on [src].")) update_appearance() + return CLICK_ACTION_SUCCESS /obj/item/reagent_containers/cup/glass/waterbottle/is_refillable() if(cap_on) @@ -436,6 +436,7 @@ amount_per_transfer_from_this = 10 volume = 100 isGlass = FALSE + interaction_flags_click = NEED_HANDS|FORBID_TELEKINESIS_REACH /// Whether or not poured drinks should use custom names and descriptions var/using_custom_drinks = FALSE /// Name custom drinks will have @@ -463,34 +464,30 @@ . += span_notice("Drinks poured from this shaker will have the following name: [custom_drink_name]") . += span_notice("Drinks poured from this shaker will have the following description: [custom_drink_desc]") -/obj/item/reagent_containers/cup/glass/shaker/AltClick(mob/user) - . = ..() - if(!user.can_perform_action(src, NEED_HANDS|FORBID_TELEKINESIS_REACH)) - return - +/obj/item/reagent_containers/cup/glass/shaker/click_alt(mob/user) if(using_custom_drinks) using_custom_drinks = FALSE disable_custom_drinks() balloon_alert(user, "custom drinks disabled") - return + return CLICK_ACTION_BLOCKING var/new_name = reject_bad_text(tgui_input_text(user, "Drink name", "Set drink name", custom_drink_name, 45, FALSE), 64) if(!new_name) balloon_alert(user, "invalid drink name!") using_custom_drinks = FALSE - return + return CLICK_ACTION_BLOCKING if(!user.can_perform_action(src, NEED_HANDS|FORBID_TELEKINESIS_REACH)) - return + return CLICK_ACTION_BLOCKING var/new_desc = reject_bad_text(tgui_input_text(user, "Drink description", "Set drink description", custom_drink_desc, 64, TRUE), 128) if(!new_desc) balloon_alert(user, "invalid drink description!") using_custom_drinks = FALSE - return + return CLICK_ACTION_BLOCKING if(!user.can_perform_action(src, NEED_HANDS|FORBID_TELEKINESIS_REACH)) - return + return CLICK_ACTION_BLOCKING using_custom_drinks = TRUE custom_drink_name = new_name @@ -498,6 +495,7 @@ enable_custom_drinks() balloon_alert(user, "now pouring custom drinks") + return CLICK_ACTION_SUCCESS /obj/item/reagent_containers/cup/glass/shaker/proc/enable_custom_drinks() RegisterSignal(src, COMSIG_REAGENTS_CUP_TRANSFER_TO, PROC_REF(handle_transfer)) diff --git a/code/modules/reagents/reagent_containers/cups/glassbottle.dm b/code/modules/reagents/reagent_containers/cups/glassbottle.dm index 4f7abbe6f20..a293aac7aa1 100644 --- a/code/modules/reagents/reagent_containers/cups/glassbottle.dm +++ b/code/modules/reagents/reagent_containers/cups/glassbottle.dm @@ -894,7 +894,8 @@ desc = "Fermented prison wine made from fruit, sugar, and despair. You probably shouldn't drink this around Security." icon_state = "trashbag1" // pruno releases air as it ferments, we don't want to simulate this in atmos, but we can make it look like it did for (var/mob/living/M in view(2, get_turf(src))) // letting people and/or narcs know when the pruno is done - to_chat(M, span_info("A pungent smell emanates from [src], like fruit puking out its guts.")) + if(HAS_TRAIT(M, TRAIT_ANOSMIA)) + to_chat(M, span_info("A pungent smell emanates from [src], like fruit puking out its guts.")) playsound(get_turf(src), 'sound/effects/bubbles2.ogg', 25, TRUE) /** diff --git a/code/modules/reagents/reagent_containers/medigel.dm b/code/modules/reagents/reagent_containers/medigel.dm index e6836c7a4c2..f6d7b116eff 100644 --- a/code/modules/reagents/reagent_containers/medigel.dm +++ b/code/modules/reagents/reagent_containers/medigel.dm @@ -32,6 +32,7 @@ "Purple" = "medigel_purple" ) + /obj/item/reagent_containers/medigel/mode_change_message(mob/user) var/squirt_mode = amount_per_transfer_from_this == initial(amount_per_transfer_from_this) to_chat(user, span_notice("You will now apply the medigel's contents in [squirt_mode ? "extended sprays":"short bursts"]. You'll now use [amount_per_transfer_from_this] units per use.")) diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index ee512224184..98ba3a13ed2 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -314,6 +314,12 @@ list_reagents = list(/datum/reagent/gravitum = 5) rename_with_volume = TRUE +/obj/item/reagent_containers/pill/ondansetron + name = "ondansetron pill" + desc = "Alleviates nausea. May cause drowsiness." + icon_state = "pill11" + list_reagents = list(/datum/reagent/medicine/ondansetron = 10) + // Pill styles for chem master /obj/item/reagent_containers/pill/style diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index a554dca6a84..350f51492cf 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -437,9 +437,14 @@ "Yellow" = "sprayer_med_yellow", "Blue" = "sprayer_med_blue") -/obj/item/reagent_containers/spray/medical/AltClick(mob/user) - if(unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY)) - reskin_obj(user) + +/obj/item/reagent_containers/spray/medical/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + + if(!current_skin) + context[SCREENTIP_CONTEXT_ALT_LMB] = "Reskin" + return CONTEXTUAL_SCREENTIP_SET + /obj/item/reagent_containers/spray/medical/reskin_obj(mob/M) ..() diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index d9ce792f1a0..a25b3936a35 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -454,8 +454,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/reagent_dispensers/wall/virusfood, 30 . = ..() AddComponent(/datum/component/simple_rotation) -/obj/structure/reagent_dispensers/plumbed/storage/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation /obj/structure/reagent_dispensers/plumbed/storage/update_overlays() . = ..() diff --git a/code/modules/reagents/withdrawal/generic_addictions.dm b/code/modules/reagents/withdrawal/generic_addictions.dm index 4eabfa1095a..c7977435f4d 100644 --- a/code/modules/reagents/withdrawal/generic_addictions.dm +++ b/code/modules/reagents/withdrawal/generic_addictions.dm @@ -183,7 +183,7 @@ /datum/addiction/medicine/withdrawal_stage_1_process(mob/living/carbon/affected_carbon, seconds_per_tick) . = ..() - if(SPT_PROB(10, seconds_per_tick)) + if(SPT_PROB(1, seconds_per_tick)) affected_carbon.emote("cough") /datum/addiction/medicine/withdrawal_enters_stage_2(mob/living/carbon/affected_carbon) @@ -216,6 +216,9 @@ /datum/addiction/medicine/withdrawal_stage_2_process(mob/living/carbon/affected_carbon, seconds_per_tick) . = ..() + if(SPT_PROB(2, seconds_per_tick)) + affected_carbon.emote("cough") + var/datum/hallucination/fake_health_doll/hallucination = health_doll_ref?.resolve() if(QDELETED(hallucination)) health_doll_ref = null @@ -235,15 +238,14 @@ /datum/addiction/medicine/withdrawal_stage_3_process(mob/living/carbon/affected_carbon, seconds_per_tick) . = ..() + if(SPT_PROB(5, seconds_per_tick)) + affected_carbon.emote("cough") + var/datum/hallucination/fake_health_doll/hallucination = health_doll_ref?.resolve() if(!QDELETED(hallucination) && SPT_PROB(5, seconds_per_tick)) hallucination.increment_fake_damage() return - if(SPT_PROB(15, seconds_per_tick)) - affected_carbon.emote("cough") - return - if(SPT_PROB(65, seconds_per_tick)) return @@ -284,12 +286,12 @@ /datum/addiction/nicotine/withdrawal_stage_2_process(mob/living/carbon/affected_carbon, seconds_per_tick) . = ..() affected_carbon.set_jitter_if_lower(20 SECONDS * seconds_per_tick) - if(SPT_PROB(10, seconds_per_tick)) + if(SPT_PROB(2, seconds_per_tick)) affected_carbon.emote("cough") /datum/addiction/nicotine/withdrawal_stage_3_process(mob/living/carbon/affected_carbon, seconds_per_tick) . = ..() affected_carbon.set_jitter_if_lower(30 SECONDS * seconds_per_tick) - if(SPT_PROB(15, seconds_per_tick)) + if(SPT_PROB(5, seconds_per_tick)) affected_carbon.emote("cough") */ diff --git a/code/modules/recycling/conveyor.dm b/code/modules/recycling/conveyor.dm index cb008252037..3c04bd924ec 100644 --- a/code/modules/recycling/conveyor.dm +++ b/code/modules/recycling/conveyor.dm @@ -37,13 +37,29 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) //Direction -> if we have a conveyor belt in that direction var/list/neighbors -/obj/machinery/conveyor/Initialize(mapload) +/obj/machinery/conveyor/Initialize(mapload, new_dir, new_id) . = ..() AddElement(/datum/element/footstep_override, priority = STEP_SOUND_CONVEYOR_PRIORITY) var/static/list/give_turf_traits = list(TRAIT_TURF_IGNORE_SLOWDOWN) AddElement(/datum/element/give_turf_traits, give_turf_traits) register_context() + if(new_dir) + setDir(new_dir) + if(new_id) + id = new_id + neighbors = list() + ///Leaving onto conveyor detection won't work at this point, but that's alright since it's an optimization anyway + ///Should be fine without it + var/static/list/loc_connections = list( + COMSIG_ATOM_EXITED = PROC_REF(conveyable_exit), + COMSIG_ATOM_ENTERED = PROC_REF(conveyable_enter), + COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON = PROC_REF(conveyable_enter) + ) + AddElement(/datum/element/connect_loc, loc_connections) + update_move_direction() + LAZYADD(GLOB.conveyors_by_id[id], src) + /obj/machinery/conveyor/examine(mob/user) . = ..() if(inverted) @@ -96,27 +112,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) icon_state = "conveyor_map_inverted" flipped = TRUE -// create a conveyor -/obj/machinery/conveyor/Initialize(mapload, new_dir, new_id) - ..() - if(new_dir) - setDir(new_dir) - if(new_id) - id = new_id - neighbors = list() - ///Leaving onto conveyor detection won't work at this point, but that's alright since it's an optimization anyway - ///Should be fine without it - var/static/list/loc_connections = list( - COMSIG_ATOM_EXITED = PROC_REF(conveyable_exit), - COMSIG_ATOM_ENTERED = PROC_REF(conveyable_enter), - COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON = PROC_REF(conveyable_enter) - ) - AddElement(/datum/element/connect_loc, loc_connections) - update_move_direction() - LAZYADD(GLOB.conveyors_by_id[id], src) - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/conveyor/LateInitialize() +/obj/machinery/conveyor/post_machine_initialize() . = ..() build_neighbors() @@ -619,9 +615,9 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) if(!attached_switch) return - INVOKE_ASYNC(src, PROC_REF(update_conveyers), port) + INVOKE_ASYNC(src, PROC_REF(update_conveyors), port) -/obj/item/circuit_component/conveyor_switch/proc/update_conveyers(datum/port/input/port) +/obj/item/circuit_component/conveyor_switch/proc/update_conveyors(datum/port/input/port) if(!attached_switch) return diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm index 9bd89517bb8..bc40b1d0394 100644 --- a/code/modules/recycling/disposal/bin.dm +++ b/code/modules/recycling/disposal/bin.dm @@ -10,6 +10,7 @@ resistance_flags = FIRE_PROOF interaction_flags_machine = INTERACT_MACHINE_OPEN | INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON obj_flags = CAN_BE_HIT + use_power = NO_POWER_USE /// The internal air reservoir of the disposal var/datum/gas_mixture/air_contents @@ -99,7 +100,8 @@ if(current_size >= STAGE_FIVE) deconstruct() -/obj/machinery/disposal/LateInitialize() +/obj/machinery/disposal/post_machine_initialize() + . = ..() //this will get a copy of the air turf and take a SEND PRESSURE amount of air from it var/atom/L = loc var/datum/gas_mixture/env = new diff --git a/code/modules/recycling/disposal/construction.dm b/code/modules/recycling/disposal/construction.dm index 4b8fef12924..903a59a9305 100644 --- a/code/modules/recycling/disposal/construction.dm +++ b/code/modules/recycling/disposal/construction.dm @@ -95,8 +95,6 @@ pipe_type = initial(temp.flip_type) update_appearance() -/obj/structure/disposalconstruct/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation // construction/deconstruction // wrench: (un)anchor diff --git a/code/modules/recycling/disposal/holder.dm b/code/modules/recycling/disposal/holder.dm index 2d964d0f8fb..fff78f74bef 100644 --- a/code/modules/recycling/disposal/holder.dm +++ b/code/modules/recycling/disposal/holder.dm @@ -172,7 +172,7 @@ for(var/obj/structure/disposalpipe/P in T) if(fdir & P.dpdir) // find pipe direction mask that matches flipped dir if(QDELING(P)) - to_chat(world, "DEBUG -- [src] here, new pipe is being thanos'd") + CRASH("Pipe is being deleted while being used by a disposal holder at ([P.x], [P.y], [P.z]") return P // if no matching pipe, return null return null diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index f11ad91e002..2497af7e54c 100644 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -400,10 +400,10 @@ payments_acc = null to_chat(user, span_notice("You clear the registered account.")) -/obj/item/sales_tagger/AltClick(mob/user) - . = ..() +/obj/item/sales_tagger/click_alt(mob/user) var/potential_cut = input("How much would you like to pay out to the registered card?","Percentage Profit ([round(cut_min*100)]% - [round(cut_max*100)]%)") as num|null if(!potential_cut) cut_multiplier = initial(cut_multiplier) cut_multiplier = clamp(round(potential_cut/100, cut_min), cut_min, cut_max) to_chat(user, span_notice("[round(cut_multiplier*100)]% profit will be received if a package with a barcode is sold.")) + return CLICK_ACTION_SUCCESS diff --git a/code/modules/religion/burdened/psyker.dm b/code/modules/religion/burdened/psyker.dm index bd063dea439..1531d07f5ea 100644 --- a/code/modules/religion/burdened/psyker.dm +++ b/code/modules/religion/burdened/psyker.dm @@ -341,7 +341,7 @@ else times_dry_fired = 0 var/turf/target_turf = get_offset_target_turf(get_ranged_target_turf(owner, owner.dir, 7), dx = rand(-1, 1), dy = rand(-1, 1)) - held_gun.process_fire(target_turf, owner, TRUE, null, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)) + held_gun.process_fire(target_turf, owner, TRUE, null, pick(GLOB.all_body_zones)) held_gun.semicd = FALSE /datum/action/cooldown/spell/charged/psychic_booster diff --git a/code/modules/requests/request_manager.dm b/code/modules/requests/request_manager.dm index dd6d8d42a48..74a40304f7a 100644 --- a/code/modules/requests/request_manager.dm +++ b/code/modules/requests/request_manager.dm @@ -163,17 +163,18 @@ GLOBAL_DATUM_INIT(requests, /datum/request_manager, new) switch(action) if ("pp") - var/mob/M = request.owner?.mob - usr.client.holder.show_player_panel(M) + SSadmin_verbs.dynamic_invoke_verb(ui.user, /datum/admin_verb/show_player_panel, request.owner?.mob) return TRUE + if ("vv") var/mob/M = request.owner?.mob usr.client.debug_variables(M) return TRUE + if ("sm") - var/mob/M = request.owner?.mob - usr.client.cmd_admin_subtle_message(M) + SSadmin_verbs.dynamic_invoke_verb(ui.user, /datum/admin_verb/cmd_admin_subtle_message, request.owner?.mob) return TRUE + if ("flw") var/mob/M = request.owner?.mob usr.client.admin_follow(M) @@ -192,8 +193,9 @@ GLOBAL_DATUM_INIT(requests, /datum/request_manager, new) D.traitor_panel() return TRUE else - usr.client.holder.show_traitor_panel(M) + SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/show_traitor_panel, M) return TRUE + if ("logs") var/mob/M = request.owner?.mob if(!ismob(M)) @@ -201,16 +203,11 @@ GLOBAL_DATUM_INIT(requests, /datum/request_manager, new) return TRUE show_individual_logging_panel(M, null, null) return TRUE + if ("smite") - if(!check_rights(R_FUN)) - to_chat(usr, "Insufficient permissions to smite, you require +FUN", confidential = TRUE) - return TRUE - var/mob/living/carbon/human/H = request.owner?.mob - if (!H || !istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human", confidential = TRUE) - return TRUE - usr.client.smite(H) + SSadmin_verbs.dynamic_invoke_verb(ui.user, /datum/admin_verb/admin_smite, request.owner?.mob) return TRUE + if ("rply") if (request.req_type == REQUEST_PRAYER) to_chat(usr, "Cannot reply to a prayer", confidential = TRUE) diff --git a/code/modules/research/designs/autolathe/service_designs.dm b/code/modules/research/designs/autolathe/service_designs.dm index 6b8d7f474fc..e34fc5166c8 100644 --- a/code/modules/research/designs/autolathe/service_designs.dm +++ b/code/modules/research/designs/autolathe/service_designs.dm @@ -190,6 +190,19 @@ ) departmental_flags = DEPARTMENT_BITFLAG_SERVICE +/datum/design/soup_pot + name = "Soup Pot" + id = "souppot" + build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE + materials = list(/datum/material/iron =SHEET_MATERIAL_AMOUNT*5, /datum/material/bluespace =SMALL_MATERIAL_AMOUNT*4) + category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_EQUIPMENT) + build_path = /obj/item/reagent_containers/cup/soup_pot + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_KITCHEN, + ) + departmental_flags = DEPARTMENT_BITFLAG_SERVICE + /datum/design/bowl name = "Bowl" id = "bowl" diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index e17b53da692..84dcb67233d 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -189,6 +189,17 @@ ) departmental_flags = DEPARTMENT_BITFLAG_SERVICE +/datum/design/water_balloon + name = "Water Balloon" + id = "water_balloon" + build_type = PROTOLATHE | AWAY_LATHE + materials = list(/datum/material/plastic =SMALL_MATERIAL_AMOUNT*5) + build_path = /obj/item/toy/waterballoon + category = list( + RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_SERVICE + ) + departmental_flags = DEPARTMENT_BITFLAG_SERVICE + /datum/design/mesons name = "Optical Meson Scanners" desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting condition." diff --git a/code/modules/research/designs/tool_designs.dm b/code/modules/research/designs/tool_designs.dm index ee1e09b1143..392921795b9 100644 --- a/code/modules/research/designs/tool_designs.dm +++ b/code/modules/research/designs/tool_designs.dm @@ -137,7 +137,7 @@ name = "RCD anti disruption designs upgrade" desc = "Prevents interruption of RCD construction and deconstruction." id = "rcd_upgrade_anti_interrupt" - build_type = PROTOLATHE + build_type = PROTOLATHE | AWAY_LATHE materials = list( /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5, /datum/material/glass = SHEET_MATERIAL_AMOUNT * 1.25, @@ -154,7 +154,7 @@ name = "RCD cooling upgrade" desc = "Allows the RCD to more quickly perform multiple actions at once." id = "rcd_upgrade_cooling" - build_type = PROTOLATHE + build_type = PROTOLATHE | AWAY_LATHE materials = list( /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2, /datum/material/glass = SHEET_MATERIAL_AMOUNT, diff --git a/code/modules/research/destructive_analyzer.dm b/code/modules/research/destructive_analyzer.dm index 03fffcec8ca..021c282958d 100644 --- a/code/modules/research/destructive_analyzer.dm +++ b/code/modules/research/destructive_analyzer.dm @@ -53,9 +53,9 @@ addtimer(CALLBACK(src, PROC_REF(finish_loading)), 1 SECONDS) return TRUE -/obj/machinery/rnd/destructive_analyzer/AltClick(mob/user) - . = ..() +/obj/machinery/rnd/destructive_analyzer/click_alt(mob/user) unload_item() + return CLICK_ACTION_SUCCESS /obj/machinery/rnd/destructive_analyzer/update_icon_state() icon_state = "[base_icon_state][loaded_item ? "_l" : null]" @@ -115,11 +115,11 @@ say("Destructive analysis failed!") return TRUE -//Let emags in on a right click -/obj/machinery/rnd/destructive_analyzer/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) - if(is_right_clicking && istype(tool, /obj/item/card/emag)) - return NONE - return ..() +/obj/machinery/rnd/destructive_analyzer/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers) + // Cringe way to let emags insert on RMB because we still use attackby to insert + if(istype(tool, /obj/item/card/emag)) + return ITEM_INTERACT_SKIP_TO_ATTACK + return NONE //This allows people to put syndicate screwdrivers in the machine. Secondary act still passes. /obj/machinery/rnd/destructive_analyzer/screwdriver_act(mob/living/user, obj/item/tool) diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm index 8ed6ef04df0..c7a7b320345 100644 --- a/code/modules/research/machinery/_production.dm +++ b/code/modules/research/machinery/_production.dm @@ -452,12 +452,12 @@ drop_direction = direction balloon_alert(usr, "dropping [dir2text(drop_direction)]") -/obj/machinery/rnd/production/AltClick(mob/user) - . = ..() - if(!drop_direction || !can_interact(user)) - return +/obj/machinery/rnd/production/click_alt(mob/user) + if(drop_direction == 0) + return CLICK_ACTION_BLOCKING if(busy) balloon_alert(user, "busy printing!") - return + return CLICK_ACTION_BLOCKING balloon_alert(user, "drop direction reset") drop_direction = 0 + return CLICK_ACTION_SUCCESS diff --git a/code/modules/research/ordnance/doppler_array.dm b/code/modules/research/ordnance/doppler_array.dm index 7afe201f360..5e44c2dc703 100644 --- a/code/modules/research/ordnance/doppler_array.dm +++ b/code/modules/research/ordnance/doppler_array.dm @@ -250,8 +250,6 @@ SIGNAL_HANDLER set_light_on(!(machine_stat & NOPOWER)) -/obj/machinery/doppler_array/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation /obj/machinery/doppler_array/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index e529f97eb0c..04d0c30d9e0 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -45,7 +45,7 @@ Nothing else in the console has ID requirements. return reagent.name return ID -/obj/machinery/computer/rdconsole/LateInitialize() +/obj/machinery/computer/rdconsole/post_machine_initialize() . = ..() if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research) CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, src) diff --git a/code/modules/research/rdmachines.dm b/code/modules/research/rdmachines.dm index 58d7f1f29cf..60dcc8716cc 100644 --- a/code/modules/research/rdmachines.dm +++ b/code/modules/research/rdmachines.dm @@ -24,7 +24,7 @@ set_wires(new /datum/wires/rnd(src)) register_context() -/obj/machinery/rnd/LateInitialize() +/obj/machinery/rnd/post_machine_initialize() . = ..() if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research) CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, src) diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm index e446672bc33..1bd0d3560be 100644 --- a/code/modules/research/server.dm +++ b/code/modules/research/server.dm @@ -154,17 +154,16 @@ if(HDD_OVERLOADED) . += "The front panel is dangling open. The hdd inside is destroyed and the wires are all burned." -/obj/machinery/rnd/server/master/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) +/obj/machinery/rnd/server/master/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(!tool.tool_behaviour) - return ..() - // Only antags are given the training and knowledge to disassemble this thing. - if(is_special_character(user)) - return ..() - if(user.combat_mode) return NONE - - balloon_alert(user, "you can't find an obvious maintenance hatch!") - return ITEM_INTERACT_BLOCKING + // Only antags are given the training and knowledge to disassemble this thing. + if(!is_special_character(user)) + if(user.combat_mode) + return ITEM_INTERACT_SKIP_TO_ATTACK + balloon_alert(user, "you can't find an obvious maintenance hatch!") + return ITEM_INTERACT_BLOCKING + return NONE /obj/machinery/rnd/server/master/attackby(obj/item/attacking_item, mob/user, params) if(istype(attacking_item, /obj/item/computer_disk/hdd_theft)) diff --git a/code/modules/research/server_control.dm b/code/modules/research/server_control.dm index 94a429dc6d7..24327a731a6 100644 --- a/code/modules/research/server_control.dm +++ b/code/modules/research/server_control.dm @@ -9,7 +9,7 @@ ///Connected techweb node the server is connected to. var/datum/techweb/stored_research -/obj/machinery/computer/rdservercontrol/LateInitialize() +/obj/machinery/computer/rdservercontrol/post_machine_initialize() . = ..() if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research) CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, src) diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 7b01536034c..7d64e1878b8 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -106,6 +106,7 @@ "slime_scanner", "solar_panel", "solar_tracker", + "souppot", "space_heater", "spoon", "status_display_frame", diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm index de97ea7bf69..9724bd776d8 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -58,7 +58,7 @@ stored_slimes = list() -/obj/machinery/computer/camera_advanced/xenobio/LateInitialize(mapload) +/obj/machinery/computer/camera_advanced/xenobio/post_machine_initialize() . = ..() for(var/obj/machinery/monkey_recycler/recycler in GLOB.monkey_recyclers) if(get_area(recycler.loc) == get_area(loc)) @@ -360,9 +360,9 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo // Alternate clicks for slime, monkey and open turf if using a xenobio console -/mob/living/basic/slime/AltClick(mob/user) +/mob/living/basic/slime/click_alt(mob/user) SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_ALT, src) - ..() + return CLICK_ACTION_SUCCESS /mob/living/basic/slime/ShiftClick(mob/user) SEND_SIGNAL(user, COMSIG_XENO_SLIME_CLICK_SHIFT, src) diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 1551d6eb952..7f87a08b85b 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -705,10 +705,9 @@ context[SCREENTIP_CONTEXT_ALT_LMB] = "Set potion offer reason" return CONTEXTUAL_SCREENTIP_SET -/obj/item/slimepotion/slime/sentience/AltClick(mob/living/user) - if(!can_interact(user)) - return +/obj/item/slimepotion/slime/sentience/click_alt(mob/living/user) potion_reason = tgui_input_text(user, "Enter reason for offering potion", "Intelligence Potion", potion_reason, multiline = TRUE) + return CLICK_ACTION_SUCCESS /obj/item/slimepotion/slime/sentience/attack(mob/living/dumb_mob, mob/user) if(being_used || !isliving(dumb_mob)) @@ -1082,17 +1081,3 @@ turf_type = /turf/open/floor/sepia merge_type = /obj/item/stack/tile/sepia -/obj/item/areaeditor/blueprints/slime - name = "cerulean prints" - desc = "A one use yet of blueprints made of jelly like organic material. Extends the reach of the management console." - color = "#2956B2" - -/obj/item/areaeditor/blueprints/slime/edit_area() - ..() - var/area/area = get_area(src) - for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) - for(var/turf/area_turf as anything in zlevel_turfs) - area_turf.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - area_turf.add_atom_colour("#2956B2", FIXED_COLOUR_PRIORITY) - area.area_flags |= XENOBIOLOGY_COMPATIBLE - qdel(src) diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index ff2da672213..28f344873ff 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -201,9 +201,11 @@ shuttle.setTimer(shuttle.timeLeft(1) + hijack_flight_time_increase) //give the guy more time to hijack if it's already in flight. return shuttle.hijack_status -/obj/machinery/computer/emergency_shuttle/AltClick(user) - if(isliving(user)) - attempt_hijack_stage(user) +/obj/machinery/computer/emergency_shuttle/click_alt(mob/living/user) + if(!isliving(user)) + return NONE + attempt_hijack_stage(user) + return CLICK_ACTION_SUCCESS /obj/machinery/computer/emergency_shuttle/proc/attempt_hijack_stage(mob/living/user) if(!user.CanReach(src)) @@ -826,10 +828,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/item/storage/pod, 32) return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN return ..() -/obj/item/storage/pod/AltClick(mob/user) - if(!can_interact(user)) - return - return ..() +/obj/item/storage/pod/click_alt(mob/user) + return CLICK_ACTION_SUCCESS /obj/item/storage/pod/can_interact(mob/user) if(!..()) diff --git a/code/modules/shuttle/spaceship_navigation_beacon.dm b/code/modules/shuttle/spaceship_navigation_beacon.dm index eb613be54de..41b3f5e39ed 100644 --- a/code/modules/shuttle/spaceship_navigation_beacon.dm +++ b/code/modules/shuttle/spaceship_navigation_beacon.dm @@ -5,7 +5,6 @@ icon_state = "beacon_active" base_icon_state = "beacon" density = TRUE - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION /// Locked beacons cannot be jumped to by ships. var/locked = FALSE diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm index 989ab4edc94..e5b4b0eb024 100644 --- a/code/modules/shuttle/special.dm +++ b/code/modules/shuttle/special.dm @@ -79,7 +79,6 @@ var/obj/machinery/power/emitter/energycannon/magical/our_statue var/list/mob/living/sleepers = list() var/never_spoken = TRUE - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION /obj/structure/table/abductor/wabbajack/Initialize(mapload) . = ..() @@ -89,6 +88,12 @@ STOP_PROCESSING(SSobj, src) . = ..() +/obj/structure/table/abductor/wabbajack/screwdriver_act(mob/living/user, obj/item/tool) + return NONE + +/obj/structure/table/abductor/wabbajack/wrench_act(mob/living/user, obj/item/tool) + return NONE + /obj/structure/table/abductor/wabbajack/process() if(isnull(our_statue)) our_statue = locate() in orange(4, src) @@ -173,7 +178,6 @@ /obj/structure/table/wood/shuttle_bar resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION max_integrity = 1000 var/boot_dir = 1 @@ -184,6 +188,12 @@ ) AddElement(/datum/element/connect_loc, loc_connections) +/obj/structure/table/wood/shuttle_bar/screwdriver_act(mob/living/user, obj/item/tool) + return NONE + +/obj/structure/table/wood/shuttle_bar/wrench_act(mob/living/user, obj/item/tool) + return NONE + /obj/structure/table/wood/shuttle_bar/proc/on_entered(datum/source, atom/movable/AM) SIGNAL_HANDLER var/mob/living/M = AM diff --git a/code/modules/shuttle/syndicate.dm b/code/modules/shuttle/syndicate.dm index 402a87bf6d4..08e0b0d2699 100644 --- a/code/modules/shuttle/syndicate.dm +++ b/code/modules/shuttle/syndicate.dm @@ -11,7 +11,9 @@ shuttleId = "syndicate" possible_destinations = "syndicate_away;syndicate_z5;syndicate_ne;syndicate_nw;syndicate_n;syndicate_se;syndicate_sw;syndicate_s;syndicate_custom" resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION + +/obj/machinery/computer/shuttle/syndicate/screwdriver_act(mob/living/user, obj/item/I) + return NONE /obj/machinery/computer/shuttle/syndicate/launch_check(mob/user) . = ..() diff --git a/code/modules/spells/spell_types/jaunt/shadow_walk.dm b/code/modules/spells/spell_types/jaunt/shadow_walk.dm index c5a47cd1740..c869fb19913 100644 --- a/code/modules/spells/spell_types/jaunt/shadow_walk.dm +++ b/code/modules/spells/spell_types/jaunt/shadow_walk.dm @@ -45,7 +45,7 @@ exit_jaunt(cast_on) return - playsound(get_turf(owner), 'sound/magic/ethereal_enter.ogg', 50, TRUE, -1) + playsound(get_turf(owner), 'sound/effects/nightmare_poof.ogg', 50, TRUE, -1, ignore_walls = FALSE) cast_on.visible_message(span_boldwarning("[cast_on] melts into the shadows!")) cast_on.SetAllImmobility(0) cast_on.setStaminaLoss(0, FALSE) @@ -107,7 +107,7 @@ reveal_turf.visible_message(span_boldwarning("[jaunter] is revealed by the light!")) else reveal_turf.visible_message(span_boldwarning("[jaunter] emerges from the darkness!")) - playsound(reveal_turf, 'sound/magic/ethereal_exit.ogg', 50, TRUE, -1) + playsound(reveal_turf, 'sound/effects/nightmare_reappear.ogg', 50, TRUE, -1, ignore_walls = FALSE) return ..() diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 03f87b6d741..abf3575f39e 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -344,16 +344,16 @@ for(var/datum/wound/wound as anything in wounds) switch(wound.severity) if(WOUND_SEVERITY_TRIVIAL) - // check_list += "\t [span_danger("Your [name] is suffering [wound.a_or_from] [lowertext(wound.name)].")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL + // check_list += "\t [span_danger("Your [name] is suffering [wound.a_or_from] [LOWER_TEXT(wound.name)].")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL check_list += "\t [span_danger("Your [name] is suffering [wound.a_or_from] [wound.get_topic_name(owner)].")]" // SKYRAT EDIT - Medical overhaul-ish if(WOUND_SEVERITY_MODERATE) - // check_list += "\t [span_warning("Your [name] is suffering [wound.a_or_from] [lowertext(wound.name)]!")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL + // check_list += "\t [span_warning("Your [name] is suffering [wound.a_or_from] [LOWER_TEXT(wound.name)]!")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL check_list += "\t [span_warning("Your [name] is suffering [wound.a_or_from] [wound.get_topic_name(owner)]!")]" // SKYRAT EDIT - Medical overhaul-ish if(WOUND_SEVERITY_SEVERE) - // check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [lowertext(wound.name)]!")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL + // check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [lLOWER_TEXT(wound.name)]!")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [wound.get_topic_name(owner)]!")]" // SKYRAT EDIT - Medical overhaul-ish if(WOUND_SEVERITY_CRITICAL) - // check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [lowertext(wound.name)]!!")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL + // check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [LOWER_TEXT(wound.name)]!!")]" // SKYRAT EDIT - Medical overhaul-ish - ORIGINAL check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [wound.get_topic_name(owner)]!!")]" // SKYRAT EDIT - Medical overhaul-ish for(var/obj/item/embedded_thing in embedded_objects) @@ -771,14 +771,14 @@ if(owner == new_owner) return FALSE //`null` is a valid option, so we need to use a num var to make it clear no change was made. - SEND_SIGNAL(src, COMSIG_BODYPART_CHANGED_OWNER, new_owner, owner) - if(owner) . = owner //return value is old owner clear_ownership(owner) if(new_owner) apply_ownership(new_owner) + SEND_SIGNAL(src, COMSIG_BODYPART_CHANGED_OWNER, new_owner, owner) + refresh_bleed_rate() return . diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index 783c0292bc5..7390dd84ac9 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -381,7 +381,7 @@ /mob/living/carbon/proc/regenerate_limbs(list/excluded_zones = list()) SEND_SIGNAL(src, COMSIG_CARBON_REGENERATE_LIMBS, excluded_zones) - var/list/zone_list = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) + var/list/zone_list = GLOB.all_body_zones.Copy() var/list/dismembered_by_copy = body_zone_dismembered_by?.Copy() diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index 126bd3db33a..fb0647d0fb5 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -83,7 +83,7 @@ /mob/living/carbon/proc/get_missing_limbs() RETURN_TYPE(/list) - var/list/full = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) + var/list/full = GLOB.all_body_zones.Copy() for(var/zone in full) if(get_bodypart(zone)) full -= zone @@ -100,7 +100,7 @@ return list() /mob/living/carbon/get_disabled_limbs() - var/list/full = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) + var/list/full = GLOB.all_body_zones.Copy() var/list/disabled = list() for(var/zone in full) var/obj/item/bodypart/affecting = get_bodypart(zone) diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index a5569d803b0..9cbb786d7e6 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -584,38 +584,34 @@ limb_id = BODYPART_ID_MEAT should_draw_greyscale = FALSE -/obj/item/bodypart/arm/left/flesh/Initialize(mapload, dont_spawn_flesh = FALSE) +/obj/item/bodypart/arm/left/flesh/Initialize(mapload) . = ..() - if(!dont_spawn_flesh) - new /mob/living/basic/living_limb_flesh(src, src) ADD_TRAIT(src, TRAIT_IGNORED_BY_LIVING_FLESH, BODYPART_TRAIT) + AddElement(/datum/element/living_limb_initialiser) /obj/item/bodypart/arm/right/flesh limb_id = BODYPART_ID_MEAT should_draw_greyscale = FALSE -/obj/item/bodypart/arm/right/flesh/Initialize(mapload, dont_spawn_flesh = FALSE) +/obj/item/bodypart/arm/right/flesh/Initialize(mapload) . = ..() - if(!dont_spawn_flesh) - new /mob/living/basic/living_limb_flesh(src, src) ADD_TRAIT(src, TRAIT_IGNORED_BY_LIVING_FLESH, BODYPART_TRAIT) + AddElement(/datum/element/living_limb_initialiser) /obj/item/bodypart/leg/left/flesh limb_id = BODYPART_ID_MEAT should_draw_greyscale = FALSE -/obj/item/bodypart/leg/left/flesh/Initialize(mapload, dont_spawn_flesh = FALSE) +/obj/item/bodypart/leg/left/flesh/Initialize(mapload) . = ..() - if(!dont_spawn_flesh) - new /mob/living/basic/living_limb_flesh(src, src) ADD_TRAIT(src, TRAIT_IGNORED_BY_LIVING_FLESH, BODYPART_TRAIT) + AddElement(/datum/element/living_limb_initialiser) /obj/item/bodypart/leg/right/flesh limb_id = BODYPART_ID_MEAT should_draw_greyscale = FALSE -/obj/item/bodypart/leg/right/flesh/Initialize(mapload, dont_spawn_flesh = FALSE) +/obj/item/bodypart/leg/right/flesh/Initialize(mapload) . = ..() - if(!dont_spawn_flesh) - new /mob/living/basic/living_limb_flesh(src, src) ADD_TRAIT(src, TRAIT_IGNORED_BY_LIVING_FLESH, BODYPART_TRAIT) + AddElement(/datum/element/living_limb_initialiser) diff --git a/code/modules/surgery/organs/internal/ears/_ears.dm b/code/modules/surgery/organs/internal/ears/_ears.dm index 8e9c7ae70a7..6bdf093dd47 100644 --- a/code/modules/surgery/organs/internal/ears/_ears.dm +++ b/code/modules/surgery/organs/internal/ears/_ears.dm @@ -15,17 +15,16 @@ now_fixed = "Noise slowly begins filling your ears once more." low_threshold_cleared = "The ringing in your ears has died down." - // `deaf` measures "ticks" of deafness. While > 0, the person is unable - // to hear anything. + /// `deaf` measures "ticks" of deafness. While > 0, the person is unable to hear anything. var/deaf = 0 // `damage` in this case measures long term damage to the ears, if too high, // the person will not have either `deaf` or `ear_damage` decrease // without external aid (earmuffs, drugs) - //Resistance against loud noises + /// Resistance against loud noises var/bang_protect = 0 - // Multiplier for both long term and short term ear damage + /// Multiplier for both long term and short term ear damage var/damage_multiplier = 1 /obj/item/organ/internal/ears/on_life(seconds_per_tick, times_fired) @@ -34,28 +33,98 @@ to_chat(owner, span_warning("The ringing in your ears grows louder, blocking out any external noises for a moment.")) . = ..() - // if we have non-damage related deafness like mutations, quirks or clothing (earmuffs), don't bother processing here. Ear healing from earmuffs or chems happen elsewhere + // if we have non-damage related deafness like mutations, quirks or clothing (earmuffs), don't bother processing here. + // Ear healing from earmuffs or chems happen elsewhere if(HAS_TRAIT_NOT_FROM(owner, TRAIT_DEAF, EAR_DAMAGE)) return + // no healing if failing + if(organ_flags & ORGAN_FAILING) + return + adjustEarDamage(0, -0.5 * seconds_per_tick) + if((damage > low_threshold) && SPT_PROB(damage / 60, seconds_per_tick)) + adjustEarDamage(0, 4) + SEND_SOUND(owner, sound('sound/weapons/flash_ring.ogg')) - if((organ_flags & ORGAN_FAILING)) - deaf = max(deaf, 1) // if we're failing we always have at least 1 deaf stack (and thus deafness) - else // only clear deaf stacks if we're not failing - deaf = max(deaf - (0.5 * seconds_per_tick), 0) - if((damage > low_threshold) && SPT_PROB(damage / 60, seconds_per_tick)) - adjustEarDamage(0, 4) - SEND_SOUND(owner, sound('sound/weapons/flash_ring.ogg')) +/obj/item/organ/internal/ears/apply_organ_damage(damage_amount, maximum, required_organ_flag) + . = ..() + update_temp_deafness() - if(deaf) - ADD_TRAIT(owner, TRAIT_DEAF, EAR_DAMAGE) +/obj/item/organ/internal/ears/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags) + . = ..() + update_temp_deafness() + +/obj/item/organ/internal/ears/on_mob_remove(mob/living/carbon/organ_owner, special) + . = ..() + UnregisterSignal(organ_owner, COMSIG_MOB_SAY) + REMOVE_TRAIT(organ_owner, TRAIT_DEAF, EAR_DAMAGE) + +/** + * Snowflake proc to handle temporary deafness + * + * * ddmg: Handles normal organ damage + * * ddeaf: Handles temporary deafness, 1 ddeaf = 2 seconds of deafness, by default (with no multiplier) + */ +/obj/item/organ/internal/ears/proc/adjustEarDamage(ddmg = 0, ddeaf = 0) + if(owner.status_flags & GODMODE) + update_temp_deafness() + return + + var/mod_damage = ddmg > 0 ? (ddmg * damage_multiplier) : ddmg + if(mod_damage) + apply_organ_damage(mod_damage) + var/mod_deaf = ddeaf > 0 ? (ddeaf * damage_multiplier) : ddeaf + if(mod_deaf) + deaf = max(deaf + mod_deaf, 0) + update_temp_deafness() + +/// Updates status of deafness +/obj/item/organ/internal/ears/proc/update_temp_deafness() + // if we're failing we always have at least some deaf stacks (and thus deafness) + if(organ_flags & ORGAN_FAILING) + deaf = max(deaf, 1 * damage_multiplier) + + if(isnull(owner)) + return + + if(owner.status_flags & GODMODE) + deaf = 0 + + if(deaf > 0) + if(!HAS_TRAIT_FROM(owner, TRAIT_DEAF, EAR_DAMAGE)) + RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(adjust_speech)) + ADD_TRAIT(owner, TRAIT_DEAF, EAR_DAMAGE) else REMOVE_TRAIT(owner, TRAIT_DEAF, EAR_DAMAGE) + UnregisterSignal(owner, COMSIG_MOB_SAY) -/obj/item/organ/internal/ears/proc/adjustEarDamage(ddmg, ddeaf) - if(owner.status_flags & GODMODE) +/// Being deafened by loud noises makes you shout +/obj/item/organ/internal/ears/proc/adjust_speech(datum/source, list/speech_args) + SIGNAL_HANDLER + + if(HAS_TRAIT_NOT_FROM(source, TRAIT_DEAF, EAR_DAMAGE)) return - set_organ_damage(clamp(damage + (ddmg * damage_multiplier), 0, maxHealth)) - deaf = max(deaf + (ddeaf * damage_multiplier), 0) + if(HAS_TRAIT(source, TRAIT_SIGN_LANG)) + return + + var/message = speech_args[SPEECH_MESSAGE] + // Replace only end-of-sentence punctuation with exclamation marks (hence the empty space) + // We don't wanna mess with things like ellipses + message = replacetext(message, ". ", "! ") + message = replacetext(message, "? ", "?! ") + // Special case for the last character + switch(copytext_char(message, -1)) + if(".") + if(copytext_char(message, -2) != "..") // Once again ignoring ellipses, let people trail off + message = copytext_char(message, 1, -1) + "!" + if("?") + message = copytext_char(message, 1, -1) + "?!" + if("!") + pass() + else + message += "!" + + speech_args[SPEECH_MESSAGE] = message + return COMPONENT_UPPERCASE_SPEECH /obj/item/organ/internal/ears/invincible damage_multiplier = 0 diff --git a/code/modules/surgery/organs/internal/eyes/_eyes.dm b/code/modules/surgery/organs/internal/eyes/_eyes.dm index 08fbd4e955a..7ab37382a55 100644 --- a/code/modules/surgery/organs/internal/eyes/_eyes.dm +++ b/code/modules/surgery/organs/internal/eyes/_eyes.dm @@ -527,7 +527,7 @@ set_beam_color(new_color, to_update) return TRUE if("enter_color") - var/new_color = lowertext(params["new_color"]) + var/new_color = LOWER_TEXT(params["new_color"]) var/to_update = params["to_update"] set_beam_color(new_color, to_update, sanitize = TRUE) return TRUE diff --git a/code/modules/surgery/organs/internal/lungs/_lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm index 6df5047f4af..a7d30c2aa03 100644 --- a/code/modules/surgery/organs/internal/lungs/_lungs.dm +++ b/code/modules/surgery/organs/internal/lungs/_lungs.dm @@ -266,7 +266,8 @@ var/ratio = (breath.gases[/datum/gas/oxygen][MOLES] / safe_oxygen_max) * 10 breather.apply_damage(clamp(ratio, oxy_breath_dam_min, oxy_breath_dam_max), oxy_damage_type, spread_damage = TRUE) - breather.throw_alert(ALERT_TOO_MUCH_OXYGEN, /atom/movable/screen/alert/too_much_oxy) + if(!HAS_TRAIT(breather, TRAIT_ANOSMIA)) + breather.throw_alert(ALERT_TOO_MUCH_OXYGEN, /atom/movable/screen/alert/too_much_oxy) /// Handles NOT having too much o2. only relevant if safe_oxygen_max has a value /obj/item/organ/internal/lungs/proc/safe_oxygen(mob/living/carbon/breather, datum/gas_mixture/breath, old_o2_pp) @@ -285,7 +286,8 @@ if(nitro_pp < safe_nitro_min && !HAS_TRAIT(src, TRAIT_SPACEBREATHING)) // Suffocation side-effects. // Not safe to check the old pp because of can_breath_vacuum - breather.throw_alert(ALERT_NOT_ENOUGH_NITRO, /atom/movable/screen/alert/not_enough_nitro) + if(!HAS_TRAIT(breather, TRAIT_ANOSMIA)) + breather.throw_alert(ALERT_NOT_ENOUGH_NITRO, /atom/movable/screen/alert/not_enough_nitro) var/gas_breathed = handle_suffocation(breather, nitro_pp, safe_nitro_min, breath.gases[/datum/gas/nitrogen][MOLES]) if(nitro_pp) breathe_gas_volume(breath, /datum/gas/nitrogen, /datum/gas/carbon_dioxide, volume = gas_breathed) @@ -318,7 +320,8 @@ breather.emote("cough") if((world.time - breather.co2overloadtime) > 12 SECONDS) - breather.throw_alert(ALERT_TOO_MUCH_CO2, /atom/movable/screen/alert/too_much_co2) + if(!HAS_TRAIT(breather, TRAIT_ANOSMIA)) + breather.throw_alert(ALERT_TOO_MUCH_CO2, /atom/movable/screen/alert/too_much_co2) breather.Unconscious(6 SECONDS) // Lets hurt em a little, let them know we mean business. breather.apply_damage(3, co2_damage_type, spread_damage = TRUE) @@ -337,7 +340,8 @@ // Suffocation side-effects. if(plasma_pp < safe_plasma_min && !HAS_TRAIT(src, TRAIT_SPACEBREATHING)) // Could check old_plasma_pp but vacuum breathing hates me - breather.throw_alert(ALERT_NOT_ENOUGH_PLASMA, /atom/movable/screen/alert/not_enough_plas) + if(!HAS_TRAIT(breather, TRAIT_ANOSMIA)) + breather.throw_alert(ALERT_NOT_ENOUGH_PLASMA, /atom/movable/screen/alert/not_enough_plas) // Breathe insufficient amount of Plasma, exhale CO2. var/gas_breathed = handle_suffocation(breather, plasma_pp, safe_plasma_min, breath.gases[/datum/gas/plasma][MOLES]) if(plasma_pp) @@ -362,7 +366,8 @@ // If it's the first breath with too much CO2 in it, lets start a counter, then have them pass out after 12s or so. if(old_plasma_pp < safe_plasma_max) - breather.throw_alert(ALERT_TOO_MUCH_PLASMA, /atom/movable/screen/alert/too_much_plas) + if(!HAS_TRAIT(breather, TRAIT_ANOSMIA)) + breather.throw_alert(ALERT_TOO_MUCH_PLASMA, /atom/movable/screen/alert/too_much_plas) var/ratio = (breath.gases[/datum/gas/plasma][MOLES] / safe_plasma_max) * 10 breather.apply_damage(clamp(ratio, plas_breath_dam_min, plas_breath_dam_max), plas_damage_type, spread_damage = TRUE) @@ -466,6 +471,8 @@ miasma_disease.name = "Unknown" breather.AirborneContractDisease(miasma_disease, TRUE) // Miasma side effects + if (HAS_TRAIT(breather, TRAIT_ANOSMIA)) //Anosmia quirk holder cannot smell miasma, but can get diseases from it. + return switch(miasma_pp) if(0.25 to 5) // At lower pp, give out a little warning @@ -522,7 +529,8 @@ // More N2O, more severe side-effects. Causes stun/sleep. if(old_n2o_pp < n2o_para_min) - breather.throw_alert(ALERT_TOO_MUCH_N2O, /atom/movable/screen/alert/too_much_n2o) + if(!HAS_TRAIT(breather, TRAIT_ANOSMIA)) + breather.throw_alert(ALERT_TOO_MUCH_N2O, /atom/movable/screen/alert/too_much_n2o) n2o_euphoria = EUPHORIA_ACTIVE // give them one second of grace to wake up and run away a bit! diff --git a/code/modules/surgery/organs/internal/tongue/_tongue.dm b/code/modules/surgery/organs/internal/tongue/_tongue.dm index 5807e1d5c2d..c01b5938124 100644 --- a/code/modules/surgery/organs/internal/tongue/_tongue.dm +++ b/code/modules/surgery/organs/internal/tongue/_tongue.dm @@ -462,7 +462,7 @@ GLOBAL_LIST_INIT(english_to_zombie, list()) var/list/message_word_list = splittext(message, " ") var/list/translated_word_list = list() for(var/word in message_word_list) - word = GLOB.english_to_zombie[lowertext(word)] + word = GLOB.english_to_zombie[LOWER_TEXT(word)] translated_word_list += word ? word : FALSE // all occurrences of characters "eiou" (case-insensitive) are replaced with "r" diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm index 64bd496f2bb..754335494f9 100644 --- a/code/modules/tgui/tgui.dm +++ b/code/modules/tgui/tgui.dm @@ -118,6 +118,8 @@ /datum/asset/simple/namespaced/fontawesome)) flush_queue |= window.send_asset(get_asset_datum( /datum/asset/simple/namespaced/tgfont)) + flush_queue |= window.send_asset(get_asset_datum( + /datum/asset/json/icon_ref_map)) for(var/datum/asset/asset in src_object.ui_assets(user)) flush_queue |= window.send_asset(asset) if (flush_queue) diff --git a/code/modules/tgui_input/say_modal/speech.dm b/code/modules/tgui_input/say_modal/speech.dm index 3cdfb5057d0..8fff832477c 100644 --- a/code/modules/tgui_input/say_modal/speech.dm +++ b/code/modules/tgui_input/say_modal/speech.dm @@ -45,7 +45,7 @@ client.ooc(entry) return TRUE if(ADMIN_CHANNEL) - client.cmd_admin_say(entry) + SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/cmd_admin_say, entry) return TRUE // SKYRAT EDIT ADDITION START - CUSTOMIZATION if(LOOC_CHANNEL) diff --git a/code/modules/tooltip/tooltip.dm b/code/modules/tooltip/tooltip.dm index 4b9514aa38c..9956305db26 100644 --- a/code/modules/tooltip/tooltip.dm +++ b/code/modules/tooltip/tooltip.dm @@ -112,7 +112,7 @@ Notes: return var/ui_style = user.client?.prefs?.read_preference(/datum/preference/choiced/ui_style) if(!theme && ui_style) - theme = lowertext(ui_style) + theme = LOWER_TEXT(ui_style) if(!theme) theme = "default" user.client.tooltips.show(tip_src, params, title, content, theme) diff --git a/code/modules/transport/admin.dm b/code/modules/transport/admin.dm index 9d68d967e60..63f1fbfd55a 100644 --- a/code/modules/transport/admin.dm +++ b/code/modules/transport/admin.dm @@ -1,23 +1,14 @@ -/** - * Helper tool to try and resolve tram controller errors, or reset the contents if someone put a million chickens on the tram - * and now it's slow as hell and lagging things. - */ -/datum/admins/proc/reset_tram() - set name = "Reset Tram" - set category = "Debug" +ADMIN_VERB(reset_tram, R_DEBUG|R_ADMIN, "Reset Tram", "Reset a tram controller or its contents.", ADMIN_CATEGORY_DEBUG) var/static/list/debug_tram_list = list( - TRAMSTATION_LINE_1, - BIRDSHOT_LINE_1, - BIRDSHOT_LINE_2, - HILBERT_LINE_1, + TRAMSTATION_LINE_1, + BIRDSHOT_LINE_1, + BIRDSHOT_LINE_2, + HILBERT_LINE_1, ) - if(!check_rights(R_DEBUG)) - return - var/datum/transport_controller/linear/tram/broken_controller - var/selected_transport_id = tgui_input_list(usr, "Which tram?", "Off the rails", debug_tram_list) - var/reset_type = tgui_input_list(usr, "How hard of a reset?", "How bad is it screwed up", list("Clear Tram Contents", "Controller", "Controller and Contents", "Delete Datum", "Cancel")) + var/selected_transport_id = tgui_input_list(user, "Which tram?", "Off the rails", debug_tram_list) + var/reset_type = tgui_input_list(user, "How hard of a reset?", "How bad is it screwed up", list("Clear Tram Contents", "Controller", "Controller and Contents", "Delete Datum", "Cancel")) if(isnull(reset_type) || reset_type == "Cancel") return @@ -28,40 +19,40 @@ break if(isnull(broken_controller)) - to_chat(usr, span_warning("Couldn't find a transport controller datum with ID [selected_transport_id]!")) + to_chat(user, span_warning("Couldn't find a transport controller datum with ID [selected_transport_id]!")) return switch(reset_type) if("Clear Tram Contents") - var/selection = tgui_alert(usr, "Include player mobs in the clearing?", "Contents reset [selected_transport_id]", list("Contents", "Contents and Players", "Cancel")) + var/selection = tgui_alert(user, "Include player mobs in the clearing?", "Contents reset [selected_transport_id]", list("Contents", "Contents and Players", "Cancel")) switch(selection) if("Contents") broken_controller.reset_lift_contents(foreign_objects = TRUE, foreign_non_player_mobs = TRUE, consider_player_mobs = FALSE) - message_admins("[key_name_admin(usr)] performed a contents reset of tram ID [selected_transport_id].") - log_transport("TC: [selected_transport_id]: [key_name_admin(usr)] performed a contents reset.") + message_admins("[key_name_admin(user)] performed a contents reset of tram ID [selected_transport_id].") + log_transport("TC: [selected_transport_id]: [key_name_admin(user)] performed a contents reset.") if("Contents and Players") broken_controller.reset_lift_contents(foreign_objects = TRUE, foreign_non_player_mobs = TRUE, consider_player_mobs = TRUE) - message_admins("[key_name_admin(usr)] performed a contents and player mob reset of tram ID [selected_transport_id].") - log_transport("TC: [selected_transport_id]: [key_name_admin(usr)] performed a contents and player mob reset.") + message_admins("[key_name_admin(user)] performed a contents and player mob reset of tram ID [selected_transport_id].") + log_transport("TC: [selected_transport_id]: [key_name_admin(user)] performed a contents and player mob reset.") else return if("Controller") - log_transport("TC: [selected_transport_id]: [key_name_admin(usr)] performed a controller reset, force operational.") - message_admins("[key_name_admin(usr)] performed a controller reset of tram ID [selected_transport_id].") + log_transport("TC: [selected_transport_id]: [key_name_admin(user)] performed a controller reset, force operational.") + message_admins("[key_name_admin(user)] performed a controller reset of tram ID [selected_transport_id].") broken_controller.set_operational(TRUE) broken_controller.reset_position() if("Controller and Contents") - var/selection = tgui_alert(usr, "Include player mobs in the clearing?", "Contents reset [selected_transport_id]", list("Contents", "Contents and Players", "Cancel")) + var/selection = tgui_alert(user, "Include player mobs in the clearing?", "Contents reset [selected_transport_id]", list("Contents", "Contents and Players", "Cancel")) switch(selection) if("Contents") - message_admins("[key_name_admin(usr)] performed a contents and controller reset of tram ID [selected_transport_id].") - log_transport("TC: [selected_transport_id]: [key_name_admin(usr)] performed a contents reset. Controller reset, force operational.") + message_admins("[key_name_admin(user)] performed a contents and controller reset of tram ID [selected_transport_id].") + log_transport("TC: [selected_transport_id]: [key_name_admin(user)] performed a contents reset. Controller reset, force operational.") broken_controller.reset_lift_contents(foreign_objects = TRUE, foreign_non_player_mobs = TRUE, consider_player_mobs = FALSE) if("Contents and Players") - message_admins("[key_name_admin(usr)] performed a contents/player/controller reset of tram ID [selected_transport_id].") - log_transport("TC: [selected_transport_id]: [key_name_admin(usr)] performed a contents and player mob reset. Controller reset, force operational.") + message_admins("[key_name_admin(user)] performed a contents/player/controller reset of tram ID [selected_transport_id].") + log_transport("TC: [selected_transport_id]: [key_name_admin(user)] performed a contents and player mob reset. Controller reset, force operational.") broken_controller.reset_lift_contents(foreign_objects = TRUE, foreign_non_player_mobs = TRUE, consider_player_mobs = TRUE) else return @@ -70,7 +61,7 @@ broken_controller.reset_position() if("Delete Datum") - var/confirm = tgui_alert(usr, "Deleting [selected_transport_id] will make it unrecoverable this round. Are you sure?", "Delete tram ID [selected_transport_id]", list("Yes", "Cancel")) + var/confirm = tgui_alert(user, "Deleting [selected_transport_id] will make it unrecoverable this round. Are you sure?", "Delete tram ID [selected_transport_id]", list("Yes", "Cancel")) if(confirm != "Yes") return @@ -82,4 +73,4 @@ broken_controller.cycle_doors(CYCLE_OPEN, BYPASS_DOOR_CHECKS) broken_controller.estop() qdel(broken_controller) - message_admins("[key_name_admin(usr)] performed a datum delete of tram ID [selected_transport_id].") + message_admins("[key_name_admin(user)] performed a datum delete of tram ID [selected_transport_id].") diff --git a/code/modules/transport/elevator/elev_indicator.dm b/code/modules/transport/elevator/elev_indicator.dm index 7b34f2d6105..22b9334be5a 100644 --- a/code/modules/transport/elevator/elev_indicator.dm +++ b/code/modules/transport/elevator/elev_indicator.dm @@ -36,11 +36,7 @@ /// The elevator's current floor relative to its lowest floor being 1 var/current_lift_floor = 1 -/obj/machinery/lift_indicator/Initialize(mapload) - . = ..() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/lift_indicator/LateInitialize() +/obj/machinery/lift_indicator/post_machine_initialize() . = ..() for(var/datum/transport_controller/linear/possible_match as anything in SStransport.transports_by_type[TRANSPORT_TYPE_ELEVATOR]) diff --git a/code/modules/transport/elevator/elev_panel.dm b/code/modules/transport/elevator/elev_panel.dm index 24b6e0fa317..76b95922dfe 100644 --- a/code/modules/transport/elevator/elev_panel.dm +++ b/code/modules/transport/elevator/elev_panel.dm @@ -60,19 +60,15 @@ AddElement(/datum/element/contextual_screentip_tools, tool_behaviors) AddElement(/datum/element/contextual_screentip_bare_hands, lmb_text = "Send Elevator") - // Machinery returns lateload by default via parent, - // this is just here for redundancy's sake. - . = INITIALIZE_HINT_LATELOAD - maploaded = mapload - // Maploaded panels link in LateInitialize... + // Maploaded panels link in post_machine_initialize... if(mapload) return // And non-mapload panels link in Initialize link_with_lift(log_error = FALSE) -/obj/machinery/elevator_control_panel/LateInitialize() +/obj/machinery/elevator_control_panel/post_machine_initialize() . = ..() // If we weren't maploaded, we probably already linked (or tried to link) in Initialize(). if(!maploaded) diff --git a/code/modules/transport/tram/tram_controller.dm b/code/modules/transport/tram/tram_controller.dm index 351ceab596e..624325f4996 100644 --- a/code/modules/transport/tram/tram_controller.dm +++ b/code/modules/transport/tram/tram_controller.dm @@ -708,19 +708,20 @@ /obj/machinery/transport/tram_controller/hilbert configured_transport_id = HILBERT_LINE_1 - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION + +/obj/machinery/transport/tram_controller/wrench_act_secondary(mob/living/user, obj/item/tool) + return NONE /obj/machinery/transport/tram_controller/Initialize(mapload) . = ..() register_context() if(!id_tag) id_tag = assign_random_name() - return INITIALIZE_HINT_LATELOAD /** * Mapped or built tram cabinet isn't located on a transport module. */ -/obj/machinery/transport/tram_controller/LateInitialize(mapload) +/obj/machinery/transport/tram_controller/post_machine_initialize() . = ..() SStransport.hello(src, name, id_tag) find_controller() @@ -848,7 +849,7 @@ return playsound(loc, 'sound/items/deconstruct.ogg', 50, vary = TRUE) balloon_alert(user, "unsecured") - deconstruct() + deconstruct(TRUE) return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN /obj/machinery/transport/tram_controller/screwdriver_act_secondary(mob/living/user, obj/item/tool) diff --git a/code/modules/transport/tram/tram_controls.dm b/code/modules/transport/tram/tram_controls.dm index 435b47f9d1b..0bfce56aa5c 100644 --- a/code/modules/transport/tram/tram_controls.dm +++ b/code/modules/transport/tram/tram_controls.dm @@ -54,7 +54,7 @@ var/obj/item/circuitboard/computer/tram_controls/my_circuit = circuit split_mode = my_circuit.split_mode -/obj/machinery/computer/tram_controls/LateInitialize() +/obj/machinery/computer/tram_controls/post_machine_initialize() . = ..() if(!id_tag) id_tag = assign_random_name() diff --git a/code/modules/transport/tram/tram_displays.dm b/code/modules/transport/tram/tram_displays.dm index 47fe21f2ff1..b228bb38e9b 100644 --- a/code/modules/transport/tram/tram_displays.dm +++ b/code/modules/transport/tram/tram_displays.dm @@ -51,7 +51,6 @@ TRAMSTATION_LINE_1, ) set_light(l_dir = REVERSE_DIR(dir)) - return INITIALIZE_HINT_LATELOAD /obj/machinery/transport/destination_sign/Destroy() SStransport.displays -= src @@ -61,7 +60,7 @@ . = ..() set_light(l_dir = REVERSE_DIR(dir)) -/obj/machinery/transport/destination_sign/indicator/LateInitialize(mapload) +/obj/machinery/transport/destination_sign/indicator/post_machine_initialize() . = ..() link_tram() diff --git a/code/modules/transport/tram/tram_doors.dm b/code/modules/transport/tram/tram_doors.dm index 7e21b936791..ea6fe8d32c9 100644 --- a/code/modules/transport/tram/tram_doors.dm +++ b/code/modules/transport/tram/tram_doors.dm @@ -184,7 +184,7 @@ RemoveElement(/datum/element/atmos_sensitive, mapload) return INITIALIZE_HINT_LATELOAD -/obj/machinery/door/airlock/tram/LateInitialize(mapload) +/obj/machinery/door/airlock/tram/post_machine_initialize() . = ..() INVOKE_ASYNC(src, PROC_REF(open)) SStransport.doors += src diff --git a/code/modules/transport/tram/tram_machinery.dm b/code/modules/transport/tram/tram_machinery.dm index 7371447d082..99375bfbaf5 100644 --- a/code/modules/transport/tram/tram_machinery.dm +++ b/code/modules/transport/tram/tram_machinery.dm @@ -37,8 +37,7 @@ . = ..() return INITIALIZE_HINT_LATELOAD -/obj/item/assembly/control/transport/call_button/LateInitialize(mapload) - . = ..() +/obj/item/assembly/control/transport/call_button/LateInitialize() if(!id_tag) id_tag = assign_random_name() SStransport.hello(src, name, id_tag) diff --git a/code/modules/transport/tram/tram_power.dm b/code/modules/transport/tram/tram_power.dm index ff0251e9090..45c48766db8 100644 --- a/code/modules/transport/tram/tram_power.dm +++ b/code/modules/transport/tram/tram_power.dm @@ -15,11 +15,7 @@ /// The tram platform we're connected to and providing power var/obj/effect/landmark/transport/nav_beacon/tram/platform/connected_platform -/obj/machinery/transport/power_rectifier/Initialize(mapload) - . = ..() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/transport/power_rectifier/LateInitialize(mapload) +/obj/machinery/transport/power_rectifier/post_machine_initialize() . = ..() RegisterSignal(SStransport, COMSIG_TRANSPORT_ACTIVE, PROC_REF(power_tram)) find_platform() diff --git a/code/modules/transport/tram/tram_remote.dm b/code/modules/transport/tram/tram_remote.dm index 4176117d8b2..3a45ec4e665 100644 --- a/code/modules/transport/tram/tram_remote.dm +++ b/code/modules/transport/tram/tram_remote.dm @@ -107,12 +107,9 @@ SEND_SIGNAL(src, COMSIG_TRANSPORT_REQUEST, specific_transport_id, destination, options) -/obj/item/assembly/control/transport/remote/AltClick(mob/user) - . = ..() - if(!can_interact(user)) - return - +/obj/item/assembly/control/transport/remote/click_alt(mob/user) link_tram(user) + return CLICK_ACTION_SUCCESS /obj/item/assembly/control/transport/remote/proc/link_tram(mob/user) specific_transport_id = null diff --git a/code/modules/transport/tram/tram_signals.dm b/code/modules/transport/tram/tram_signals.dm index 101ae1027a3..eb648666030 100644 --- a/code/modules/transport/tram/tram_signals.dm +++ b/code/modules/transport/tram/tram_signals.dm @@ -107,9 +107,8 @@ RegisterSignal(SStransport, COMSIG_COMMS_STATUS, PROC_REF(comms_change)) SStransport.crossing_signals += src register_context() - return INITIALIZE_HINT_LATELOAD -/obj/machinery/transport/crossing_signal/LateInitialize(mapload) +/obj/machinery/transport/crossing_signal/post_machine_initialize() . = ..() link_tram() link_sensor() @@ -170,20 +169,16 @@ obj_flags |= EMAGGED return TRUE -/obj/machinery/transport/crossing_signal/AltClick(mob/living/user) - . = ..() - if(!can_interact(user)) - return - +/obj/machinery/transport/crossing_signal/click_alt(mob/living/user) var/obj/item/tool = user.get_active_held_item() if(!panel_open || tool?.tool_behaviour != TOOL_WRENCH) - return FALSE + return CLICK_ACTION_BLOCKING tool.play_tool_sound(src, 50) setDir(turn(dir,-90)) - to_chat(user, span_notice("You rotate [src].")) + balloon_alert(user, "rotated") find_uplink() - return TRUE + return CLICK_ACTION_SUCCESS /obj/machinery/transport/crossing_signal/attackby_secondary(obj/item/weapon, mob/user, params) . = ..() @@ -510,9 +505,8 @@ /obj/machinery/transport/guideway_sensor/Initialize(mapload) . = ..() SStransport.sensors += src - return INITIALIZE_HINT_LATELOAD -/obj/machinery/transport/guideway_sensor/LateInitialize(mapload) +/obj/machinery/transport/guideway_sensor/post_machine_initialize() . = ..() pair_sensor() RegisterSignal(SStransport, COMSIG_TRANSPORT_ACTIVE, PROC_REF(wake_up)) diff --git a/code/modules/transport/tram/tram_structures.dm b/code/modules/transport/tram/tram_structures.dm index f868fe21c48..368223d1165 100644 --- a/code/modules/transport/tram/tram_structures.dm +++ b/code/modules/transport/tram/tram_structures.dm @@ -486,7 +486,6 @@ return INITIALIZE_HINT_LATELOAD /obj/structure/tram/spoiler/LateInitialize() - . = ..() RegisterSignal(SStransport, COMSIG_TRANSPORT_ACTIVE, PROC_REF(set_spoiler)) /obj/structure/tram/spoiler/add_context(atom/source, list/context, obj/item/held_item, mob/user) diff --git a/code/modules/transport/transport_module.dm b/code/modules/transport/transport_module.dm index d027cf7ba6d..a2ba6f5167b 100644 --- a/code/modules/transport/transport_module.dm +++ b/code/modules/transport/transport_module.dm @@ -96,7 +96,6 @@ return INITIALIZE_HINT_LATELOAD /obj/structure/transport/linear/LateInitialize() - . = ..() //after everything is initialized the transport controller can order everything transport_controller_datum.order_platforms_by_z_level() diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 1b5c1f931bc..fb82c4fd748 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -117,6 +117,7 @@ #include "closets.dm" #include "clothing_under_armor_subtype_check.dm" #include "combat.dm" +#include "combat_welder.dm" #include "component_tests.dm" #include "confusion.dm" #include "connect_loc.dm" @@ -168,6 +169,7 @@ #include "ling_decap.dm" #include "liver.dm" #include "load_map_security.dm" +#include "lootpanel.dm" #include "lungs.dm" #include "machine_disassembly.dm" #include "mafia.dm" @@ -255,6 +257,7 @@ #include "station_trait_tests.dm" #include "status_effect_ticks.dm" #include "stomach.dm" +#include "storage.dm" #include "strange_reagent.dm" #include "strippable.dm" #include "stuns.dm" diff --git a/code/modules/unit_tests/combat_welder.dm b/code/modules/unit_tests/combat_welder.dm new file mode 100644 index 00000000000..2fa9052d6fb --- /dev/null +++ b/code/modules/unit_tests/combat_welder.dm @@ -0,0 +1,26 @@ +/datum/unit_test/welder_combat + +/datum/unit_test/welder_combat/Run() + var/mob/living/carbon/human/tider = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left) + var/mob/living/carbon/human/victim = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left) + var/obj/item/weldingtool/weapon = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left) + + tider.put_in_active_hand(weapon, forced = TRUE) + tider.set_combat_mode(TRUE) + weapon.attack_self(tider) + weapon.melee_attack_chain(tider, victim) + + TEST_ASSERT_NOTEQUAL(victim.getFireLoss(), 0, "Victim did not get burned by welder.") + TEST_ASSERT_EQUAL(weapon.get_fuel(), weapon.max_fuel - 1, "Welder did not consume fuel on attacking a mob") + + var/obj/structure/blob/blobby = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left) + weapon.melee_attack_chain(tider, blobby) + + TEST_ASSERT_NOTEQUAL(blobby.get_integrity(), blobby.max_integrity, "Blob did not get burned by welder.") + TEST_ASSERT_EQUAL(weapon.get_fuel(), weapon.max_fuel - 2, "Welder did not consume fuel on attacking a blob") + + weapon.force = 999 + weapon.melee_attack_chain(tider, blobby) + + TEST_ASSERT(QDELETED(blobby), "Blob was not destroyed by welder.") + TEST_ASSERT_EQUAL(weapon.get_fuel(), weapon.max_fuel - 3, "Welder did not consume fuel on deleting a blob") diff --git a/code/modules/unit_tests/lootpanel.dm b/code/modules/unit_tests/lootpanel.dm new file mode 100644 index 00000000000..c0bec13288c --- /dev/null +++ b/code/modules/unit_tests/lootpanel.dm @@ -0,0 +1,34 @@ +/datum/unit_test/lootpanel + abstract_type = /datum/unit_test/lootpanel + +/datum/unit_test/lootpanel/contents/Run() + var/datum/client_interface/mock_client = new() + var/datum/lootpanel/panel = new(mock_client) + var/mob/living/carbon/human/labrat = allocate(/mob/living/carbon/human/consistent) + mock_client.mob = labrat + var/turf/one_over = locate(run_loc_floor_bottom_left.x + 1, run_loc_floor_bottom_left.y, run_loc_floor_bottom_left.z) + var/obj/item/storage/toolbox/box = allocate(/obj/item/storage/toolbox, one_over) + + panel.open(one_over) + TEST_ASSERT_EQUAL(length(panel.contents), 2, "Contents should populate on open") + TEST_ASSERT_EQUAL(length(panel.to_image), 2, "to_image should've populated (unit testing)") + TEST_ASSERT_EQUAL(panel.contents[1].item, one_over, "First item should be the source turf") + + var/datum/search_object/searchable = panel.contents[2] + TEST_ASSERT_EQUAL(searchable.item, box, "Second item should be the box") + + qdel(box) + TEST_ASSERT_EQUAL(length(panel.contents), 1, "Contents should update on searchobj deleted") + TEST_ASSERT_EQUAL(length(panel.to_image), 1, "to_image should update on searchobj deleted") + + var/obj/item/storage/toolbox/new_box = allocate(/obj/item/storage/toolbox, one_over) + TEST_ASSERT_EQUAL(length(panel.contents), 1, "Contents shouldn't update, we're dumb") + TEST_ASSERT_EQUAL(length(panel.to_image), 1, "to_image shouldn't update, we're dumb") + + panel.populate_contents() // this also calls reset_contents bc length(contents) + TEST_ASSERT_EQUAL(length(panel.contents), 2, "Contents should repopulate with the new toolbox") + + panel.populate_contents() + TEST_ASSERT_EQUAL(length(panel.contents), 2, "Panel shouldnt dupe searchables if reopened") + + mock_client.mob = null diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_tallboy.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_tallboy.png index 262353dc0a9..83afcbc2a48 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_tallboy.png and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_tallboy.png differ diff --git a/code/modules/unit_tests/storage.dm b/code/modules/unit_tests/storage.dm new file mode 100644 index 00000000000..82ac035ed7e --- /dev/null +++ b/code/modules/unit_tests/storage.dm @@ -0,0 +1,22 @@ +/// Test storage datums +/datum/unit_test/storage + +/datum/unit_test/storage/Run() + var/obj/item/big_thing = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left) + big_thing.w_class = WEIGHT_CLASS_BULKY + var/obj/item/small_thing = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left) + small_thing.w_class = WEIGHT_CLASS_SMALL + + var/obj/item/storage/backpack/storage_item = allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left) + + storage_item.atom_storage.attempt_insert(big_thing) + TEST_ASSERT_NOTEQUAL(big_thing.loc, storage_item, "A bulky item should have failed to insert into a backpack") + + storage_item.atom_storage.attempt_insert(small_thing) + TEST_ASSERT_EQUAL(small_thing.loc, storage_item, "A small item should have successfully inserted into a backpack") + + small_thing.update_weight_class(WEIGHT_CLASS_NORMAL) + TEST_ASSERT_EQUAL(small_thing.loc, storage_item, "A small item changed into normal size should not have ejected from the backpack") + + small_thing.update_weight_class(WEIGHT_CLASS_BULKY) + TEST_ASSERT_NOTEQUAL(small_thing.loc, storage_item, "A small item changed back into bulky size should have ejected from the backpack") diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm index 7cee1b6541c..995764e0bb7 100644 --- a/code/modules/vehicles/mecha/_mecha.dm +++ b/code/modules/vehicles/mecha/_mecha.dm @@ -272,7 +272,7 @@ /// If the former occupants get polymorphed, mutated, chestburstered, /// or otherwise replaced by another mob, that mob is no longer in .occupants /// and gets deleted with the mech. However, they do remain in .contents - var/list/potential_occupants = contents ^ occupants + var/list/potential_occupants = contents | occupants for(var/mob/buggy_ejectee in potential_occupants) mob_exit(buggy_ejectee, silent = TRUE) diff --git a/code/modules/vehicles/mecha/mech_fabricator.dm b/code/modules/vehicles/mecha/mech_fabricator.dm index 54acd183aff..2dce26624ad 100644 --- a/code/modules/vehicles/mecha/mech_fabricator.dm +++ b/code/modules/vehicles/mecha/mech_fabricator.dm @@ -55,7 +55,7 @@ RefreshParts() //Recalculating local material sizes if the fab isn't linked return ..() -/obj/machinery/mecha_part_fabricator/LateInitialize() +/obj/machinery/mecha_part_fabricator/post_machine_initialize() . = ..() if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research) CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, src) @@ -127,14 +127,12 @@ if(panel_open) . += span_notice("Alt-click to rotate the output direction.") -/obj/machinery/mecha_part_fabricator/AltClick(mob/user) - . = ..() - if(!user.can_perform_action(src)) - return - if(panel_open) - dir = turn(dir, -90) - balloon_alert(user, "rotated to [dir2text(dir)].") - return TRUE +/obj/machinery/mecha_part_fabricator/click_alt(mob/user) + if(!panel_open) + return CLICK_ACTION_BLOCKING + dir = turn(dir, -90) + balloon_alert(user, "rotated to [dir2text(dir)].") + return CLICK_ACTION_SUCCESS /** * Updates the `final_sets` and `buildable_parts` for the current mecha fabricator. diff --git a/code/modules/vehicles/mecha/mecha_actions.dm b/code/modules/vehicles/mecha/mecha_actions.dm index 2b410bd60c7..d544c829667 100644 --- a/code/modules/vehicles/mecha/mecha_actions.dm +++ b/code/modules/vehicles/mecha/mecha_actions.dm @@ -91,14 +91,15 @@ chassis.toggle_strafe() -/obj/vehicle/sealed/mecha/AltClick(mob/living/user) - if(!(user in occupants) || !user.can_perform_action(src)) - return +/obj/vehicle/sealed/mecha/click_alt(mob/living/user) + if(!(user in occupants)) + return CLICK_ACTION_BLOCKING if(!(user in return_controllers_with_flag(VEHICLE_CONTROL_DRIVE))) to_chat(user, span_warning("You're in the wrong seat to control movement.")) - return + return CLICK_ACTION_BLOCKING toggle_strafe() + return CLICK_ACTION_SUCCESS /obj/vehicle/sealed/mecha/proc/toggle_strafe() if(!(mecha_flags & CAN_STRAFE)) diff --git a/code/modules/vehicles/ridden.dm b/code/modules/vehicles/ridden.dm index 33f81184e9a..52c7924d72f 100644 --- a/code/modules/vehicles/ridden.dm +++ b/code/modules/vehicles/ridden.dm @@ -5,6 +5,7 @@ buckle_lying = 0 pass_flags_self = PASSTABLE COOLDOWN_DECLARE(message_cooldown) + interaction_flags_click = NEED_DEXTERITY /obj/vehicle/ridden/examine(mob/user) . = ..() @@ -39,16 +40,17 @@ inserted_key.forceMove(drop_location()) inserted_key = I -/obj/vehicle/ridden/AltClick(mob/user) - if(!inserted_key || !user.can_perform_action(src, NEED_DEXTERITY)) - return ..() +/obj/vehicle/ridden/click_alt(mob/user) + if(!inserted_key) + return CLICK_ACTION_BLOCKING if(!is_occupant(user)) to_chat(user, span_warning("You must be riding the [src] to remove [src]'s key!")) - return + return CLICK_ACTION_BLOCKING to_chat(user, span_notice("You remove \the [inserted_key] from \the [src].")) inserted_key.forceMove(drop_location()) user.put_in_hands(inserted_key) inserted_key = null + return CLICK_ACTION_SUCCESS /obj/vehicle/ridden/user_buckle_mob(mob/living/M, mob/user, check_loc = TRUE) if(!in_range(user, src) || !in_range(M, src)) diff --git a/code/modules/vehicles/wheelchair.dm b/code/modules/vehicles/wheelchair.dm index e7b3d9b3a56..92fcb995f76 100644 --- a/code/modules/vehicles/wheelchair.dm +++ b/code/modules/vehicles/wheelchair.dm @@ -63,8 +63,6 @@ qdel(src) return ITEM_INTERACT_SUCCESS -/obj/vehicle/ridden/wheelchair/AltClick(mob/user) - return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation /obj/vehicle/ridden/wheelchair/update_overlays() . = ..() diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm index 42f6ff2a436..29641441e67 100644 --- a/code/modules/vending/_vending.dm +++ b/code/modules/vending/_vending.dm @@ -1157,8 +1157,6 @@ GLOBAL_LIST_EMPTY(vending_machines_to_restock) /obj/machinery/vending/exchange_parts(mob/user, obj/item/storage/part_replacer/replacer) if(!istype(replacer)) return FALSE - if(!replacer.works_from_distance) - return FALSE if(!component_parts || !refill_canister) return FALSE diff --git a/code/modules/vending/runic_vendor.dm b/code/modules/vending/runic_vendor.dm index 3edb5b27264..f338340c8b1 100644 --- a/code/modules/vending/runic_vendor.dm +++ b/code/modules/vending/runic_vendor.dm @@ -9,6 +9,7 @@ vend_reply = "Please, stand still near the vending machine for your special package!" resistance_flags = FIRE_PROOF light_mask = "RunicVendor-light-mask" + obj_flags = parent_type::obj_flags | NO_DEBRIS_AFTER_DECONSTRUCTION /// How long the vendor stays up before it decays. var/time_to_decay = 30 SECONDS /// Area around the vendor that will pushback nearby mobs. @@ -60,15 +61,16 @@ return . +/obj/machinery/vending/runic_vendor/handle_deconstruct(disassembled) + SHOULD_NOT_OVERRIDE(TRUE) -/obj/machinery/vending/runic_vendor/Destroy() visible_message(span_warning("[src] flickers and disappears!")) playsound(src,'sound/weapons/resonator_blast.ogg',25,TRUE) return ..() /obj/machinery/vending/runic_vendor/proc/runic_explosion() explosion(src, light_impact_range = 2) - qdel(src) + deconstruct(FALSE) /obj/machinery/vending/runic_vendor/proc/runic_pulse() var/pulse_locs = spiral_range_turfs(pulse_distance, get_turf(src)) @@ -82,10 +84,9 @@ mob_to_be_pulsed_back.throw_at(target, 4, 4) /obj/machinery/vending/runic_vendor/screwdriver_act(mob/living/user, obj/item/I) - explosion(src, light_impact_range = 2) - qdel(src) + runic_explosion() /obj/machinery/vending/runic_vendor/proc/decay() - qdel(src) + deconstruct(FALSE) #undef PULSE_DISTANCE_RANGE diff --git a/code/modules/wiremod/components/action/equpiment_action.dm b/code/modules/wiremod/components/action/equpiment_action.dm index 54150ca44d6..641722c595b 100644 --- a/code/modules/wiremod/components/action/equpiment_action.dm +++ b/code/modules/wiremod/components/action/equpiment_action.dm @@ -89,4 +89,4 @@ for(var/ref in granted_to) var/datum/action/granted_action = granted_to[ref] granted_action.name = button_name.value || "Action" - granted_action.button_icon_state = "bci_[replacetextEx(lowertext(icon_options.value), " ", "_")]" + granted_action.button_icon_state = "bci_[replacetextEx(LOWER_TEXT(icon_options.value), " ", "_")]" diff --git a/code/modules/wiremod/components/string/textcase.dm b/code/modules/wiremod/components/string/textcase.dm index ac289654236..70b67740b41 100644 --- a/code/modules/wiremod/components/string/textcase.dm +++ b/code/modules/wiremod/components/string/textcase.dm @@ -41,7 +41,7 @@ var/result switch(textcase_options.value) if(COMP_TEXT_LOWER) - result = lowertext(value) + result = LOWER_TEXT(value) if(COMP_TEXT_UPPER) result = uppertext(value) diff --git a/code/modules/wiremod/core/admin_panel.dm b/code/modules/wiremod/core/admin_panel.dm index 74e72ad5efe..9a262cb5e4c 100644 --- a/code/modules/wiremod/core/admin_panel.dm +++ b/code/modules/wiremod/core/admin_panel.dm @@ -1,10 +1,7 @@ -/// An admin verb to view all circuits, plus useful information -/datum/admins/proc/view_all_circuits() - set category = "Admin.Game" - set name = "View All Circuits" +ADMIN_VERB(view_all_circuits, R_ADMIN, "View All Circuits", "List all circuits in the game.", ADMIN_CATEGORY_GAME) var/static/datum/circuit_admin_panel/circuit_admin_panel = new - circuit_admin_panel.ui_interact(usr) + circuit_admin_panel.ui_interact(user.mob) /datum/circuit_admin_panel @@ -66,9 +63,10 @@ usr.client?.debug_variables(circuit) if ("open_circuit") circuit.ui_interact(usr) + if ("open_player_panel") var/datum/mind/inserter = circuit.inserter_mind?.resolve() - usr.client?.holder?.show_player_panel(inserter?.current) + SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/show_player_panel, inserter?.current) return TRUE diff --git a/code/modules/wiremod/core/component.dm b/code/modules/wiremod/core/component.dm index 530f73ded8c..4d8344e1e6a 100644 --- a/code/modules/wiremod/core/component.dm +++ b/code/modules/wiremod/core/component.dm @@ -77,7 +77,7 @@ /obj/item/circuit_component/Initialize(mapload) . = ..() if(name == COMPONENT_DEFAULT_NAME) - name = "[lowertext(display_name)] [COMPONENT_DEFAULT_NAME]" + name = "[LOWER_TEXT(display_name)] [COMPONENT_DEFAULT_NAME]" populate_options() populate_ports() if((circuit_flags & CIRCUIT_FLAG_INPUT_SIGNAL) && !trigger_input) diff --git a/code/modules/wiremod/core/component_printer.dm b/code/modules/wiremod/core/component_printer.dm index 7c691e3a4c4..370a6cfea52 100644 --- a/code/modules/wiremod/core/component_printer.dm +++ b/code/modules/wiremod/core/component_printer.dm @@ -24,7 +24,7 @@ . = ..() materials = AddComponent(/datum/component/remote_materials, mapload) -/obj/machinery/component_printer/LateInitialize() +/obj/machinery/component_printer/post_machine_initialize() . = ..() if(!CONFIG_GET(flag/no_default_techweb_link) && !techweb) CONNECT_TO_RND_SERVER_ROUNDSTART(techweb, src) diff --git a/code/modules/wiremod/core/duplicator.dm b/code/modules/wiremod/core/duplicator.dm index 2f248d11a89..25e83326804 100644 --- a/code/modules/wiremod/core/duplicator.dm +++ b/code/modules/wiremod/core/duplicator.dm @@ -220,30 +220,24 @@ GLOBAL_LIST_INIT(circuit_dupe_whitelisted_types, list( rel_x = component_data["rel_x"] rel_y = component_data["rel_y"] -/client/proc/load_circuit() - set name = "Load Circuit" - set category = "Admin.Fun" - - if(!check_rights(R_VAREDIT)) - return - +ADMIN_VERB(load_circuit, R_VAREDIT, "Load Circuit", "Loads a circuit from a file or direct input.", ADMIN_CATEGORY_FUN) var/list/errors = list() - var/option = alert(usr, "Load by file or direct input?", "Load by file or string", "File", "Direct Input") + var/option = alert(user, "Load by file or direct input?", "Load by file or string", "File", "Direct Input") var/txt switch(option) if("File") - txt = file2text(input(usr, "Input File") as null|file) + txt = file2text(input(user, "Input File") as null|file) if("Direct Input") - txt = input(usr, "Input JSON", "Input JSON") as text|null + txt = input(user, "Input JSON", "Input JSON") as text|null if(!txt) return - var/obj/item/integrated_circuit/loaded/circuit = new(mob.drop_location()) + var/obj/item/integrated_circuit/loaded/circuit = new(user.mob.drop_location()) circuit.load_circuit_data(txt, errors) if(length(errors)) - to_chat(src, span_warning("The following errors were found whilst compiling the circuit data:")) + to_chat(user, span_warning("The following errors were found whilst compiling the circuit data:")) for(var/error in errors) - to_chat(src, span_warning(error)) + to_chat(user, span_warning(error)) diff --git a/code/modules/wiremod/shell/controller.dm b/code/modules/wiremod/shell/controller.dm index ad03867b89b..b46dad3673f 100644 --- a/code/modules/wiremod/shell/controller.dm +++ b/code/modules/wiremod/shell/controller.dm @@ -71,9 +71,9 @@ */ /obj/item/circuit_component/controller/proc/send_alternate_signal(atom/source, mob/user) SIGNAL_HANDLER - if(!user.Adjacent(source)) - return + handle_trigger(source, user, "alternate", alt) + return CLICK_ACTION_SUCCESS /** diff --git a/code/modules/wiremod/shell/module.dm b/code/modules/wiremod/shell/module.dm index 6f9a3dda93b..9061bac3e30 100644 --- a/code/modules/wiremod/shell/module.dm +++ b/code/modules/wiremod/shell/module.dm @@ -106,7 +106,7 @@ action_comp.granted_to[REF(user)] = src circuit_component = action_comp name = action_comp.button_name.value - button_icon_state = "bci_[replacetextEx(lowertext(action_comp.icon_options.value), " ", "_")]" + button_icon_state = "bci_[replacetextEx(LOWER_TEXT(action_comp.icon_options.value), " ", "_")]" /datum/action/item_action/mod/pinnable/circuit/Destroy() circuit_component.granted_to -= REF(pinner) diff --git a/html/changelogs/AutoChangeLog-pr-1367.yml b/html/changelogs/AutoChangeLog-pr-1367.yml deleted file mode 100644 index 7cd89d745b8..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1367.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "kaylexis" -delete-after: True -changes: - - rscadd: "Adds Plant Gene disk to biogen" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1383.yml b/html/changelogs/AutoChangeLog-pr-1383.yml deleted file mode 100644 index 15d8e67d88e..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1383.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Swiftfeather" -delete-after: True -changes: - - rscadd: "Blind crew are no longer barred from being heads of staff (except HoS)." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1396.yml b/html/changelogs/AutoChangeLog-pr-1396.yml deleted file mode 100644 index cecb32dea0b..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1396.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "PhazeJump" -delete-after: True -changes: - - rscadd: "wings: Moth (Bluespace)" - - rscadd: "wings: Moth (Strawberry)" - - rscadd: "wings: Moth (Clockwork)" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1402.yml b/html/changelogs/AutoChangeLog-pr-1402.yml deleted file mode 100644 index 12e59dfc31a..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1402.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Swiftfeather" -delete-after: True -changes: - - balance: "Makes bluespace crystal teleportation take time." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1403.yml b/html/changelogs/AutoChangeLog-pr-1403.yml deleted file mode 100644 index 27deb45b99e..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1403.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "VrazzleDazzle" -delete-after: True -changes: - - image: "Added a new UI theme, Blue-98!" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1408.yml b/html/changelogs/AutoChangeLog-pr-1408.yml deleted file mode 100644 index 4ed53bced4b..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1408.yml +++ /dev/null @@ -1,10 +0,0 @@ -author: "tmyqlfpir" -delete-after: True -changes: - - qol: "Various tweaks to Dauntless service and medical" - - rscadd: "Add new camera kill switches to the Dauntless" - - rscadd: "Add (non-spawned) space version of Dauntless" - - rscadd: "Add new storage room to Dauntless" - - balance: "Dauntless cyborgs will have their cameras automatically removed" - - balance: "Interdyne Powerator has 2x efficiency" - - rscadd: "Created Interdyne injectors to assign non-spawned crew as Syndicate faction" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1413.yml b/html/changelogs/AutoChangeLog-pr-1413.yml deleted file mode 100644 index 8f3c1420951..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1413.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "BurgerBB" -delete-after: True -changes: - - rscadd: "Moonstation Upstream Merge and Bonuses" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1418.yml b/html/changelogs/AutoChangeLog-pr-1418.yml deleted file mode 100644 index b867cb07070..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1418.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "StrangeWeirdKitten" -delete-after: True -changes: - - balance: "Abductor sleep is 30 seconds instead of 2 minutes" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1421.yml b/html/changelogs/AutoChangeLog-pr-1421.yml deleted file mode 100644 index b7709e1c40c..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1421.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Iamgoofball" -delete-after: True -changes: - - balance: "Takes the ashwalker translation necklace out of the loadout; ashwalker translation is supposed to be rare/craftable with resource/Curator, not a roundstart thing any crewmember can have." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1423.yml b/html/changelogs/AutoChangeLog-pr-1423.yml deleted file mode 100644 index 94d661edb5a..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1423.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Majkl-J" -delete-after: True -changes: - - bugfix: "Fixes horrendous ui design" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1427.yml b/html/changelogs/AutoChangeLog-pr-1427.yml deleted file mode 100644 index 2d6007e48ca..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1427.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "VrazzleDazzle" -delete-after: True -changes: - - rscdel: "The PKA variants have been temporarily pruned due to a licensing issue with Kahraman Industries." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1428.yml b/html/changelogs/AutoChangeLog-pr-1428.yml deleted file mode 100644 index 1700687f86a..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1428.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "BurgerBB" -delete-after: True -changes: - - bugfix: "Fixes assistants always spawning at the Interlink roundstart." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1432.yml b/html/changelogs/AutoChangeLog-pr-1432.yml deleted file mode 100644 index a45a60ee4d8..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1432.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Swiftfeather" -delete-after: True -changes: - - code_imp: "The way mobs idle has been refactored, please report any issues with non-reactive mobs" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1434.yml b/html/changelogs/AutoChangeLog-pr-1434.yml deleted file mode 100644 index 404e9d76fa8..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1434.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "BurgerBB" -delete-after: True -changes: - - rscadd: "Improves Moonstation Disposals + Fixes missing wires for Medical Storage and NTRep office." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1435.yml b/html/changelogs/AutoChangeLog-pr-1435.yml deleted file mode 100644 index 54851828cd7..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1435.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "IgiariValkyr" -delete-after: True -changes: - - rscadd: "Latex Heels to loadout" - - qol: "Filing cabinets in the Interlink office are now actually stacked together" - - bugfix: "PLAP capsule now has the colors actually described in the description" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1436.yml b/html/changelogs/AutoChangeLog-pr-1436.yml deleted file mode 100644 index 2f1e0314163..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1436.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "pixelkitty286" -delete-after: True -changes: - - rscadd: "The PKA variants." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-1439.yml b/html/changelogs/AutoChangeLog-pr-1439.yml deleted file mode 100644 index 2280eb2ed32..00000000000 --- a/html/changelogs/AutoChangeLog-pr-1439.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "destrucktoid" -delete-after: True -changes: - - balance: "Bloodsuckers can no longer kill or hurt people by drinking from them without at least a passive grab." \ No newline at end of file diff --git a/html/changelogs/archive/2024-04.yml b/html/changelogs/archive/2024-04.yml index f6e6ba8c939..f37015b57d3 100644 --- a/html/changelogs/archive/2024-04.yml +++ b/html/changelogs/archive/2024-04.yml @@ -397,167 +397,7 @@ - rscadd: added the research skill - balance: experisci scanner affected by research skill - balance: xenoarch affected by research skill -2024-04-20: - '@Crumpaloo, @Majkl-J': - - image: New foxtrot peacekeeper borg model, sprites by Crumpaloo - - code_imp: Moved around cyborg dmi defines to give the precompiler a break - - config: Development config now has both sec and peace cyborg modules enabled - Arturlang: - - rscadd: Adds backup ways for the book of kindred to spawn, either spawning on - a curator or on the codex gigas - - rscadd: Decapacitated bloodsuckers can now talk! - - rscadd: The stat bar will show you the threshold for exiting frenzy now too when - you are frenzying. - - rscadd: Bloodsucker abilities now will show their level when you hover over them. - Trust me, this was really neccessary. - - rscadd: Tremere now also get informed of how much blood they need to pay for level - ups. - - rscadd: At level 3, haste will now remove stuns and do a non-stunning dash - - rscadd: Bloodsucker blood display now always updates when a bloodsucker's blood - level is changed - - rscadd: Bloodsuckers can now examine hearts to see if they are valid for the heart - thief objective - - rscadd: Bloodsucker vassals now clean up any traits gained from their tenure as - a vampire's minion. - - rscadd: Favorite vassals now properly clean up their effects once the antag datum - is lost. - - rscadd: Bloodsucker synths will be able to heal their prosthetic limbs, but normal - bloodsuckers still cannot. - - rscadd: When you exiit torpor as a bloodsucker, you will completely heal any toxin - and oxygen damage, as you should already be immune to it. This is a safety feature. - - rscadd: Entering a coffin will normalize your temperature and extinguish you if - you're on fire, if you are a bloodsucker. - - bugfix: bloodsucker vampire bats will no longer /list you when attacking - - bugfix: Hopefully fixes some torpor loops related to frenzy - - bugfix: Hopefully fixes bloodsuckers cryoing not removing vassal datums - - bugfix: Bloodsuckers can no longer use veil of many faces while unconcious - - bugfix: lizard bloodsuckers will no longer suffer from heat for a long time - - bugfix: The ventrue objective now properly succeeds if you have sired a vampire - - bugfix: Livers are no longer required for bloodsuckers to live, as it caused them - toxin damage which overrode the trait that made them immune to toxins. - - bugfix: Entering torpor now accounts for all damage types, even when you should - be immune to them. This is to ensure you enter torpor to heal those damage types - in the case of odd behaviour. - - balance: coffins should now set your temperature to normal and extinguish you. - - balance: bloodsucker level up cost is now 15% of max blood, down from 20% - - balance: Caps humantiy loss at 50 humanity/500 blood to frenzy, and makes it remove - your masquerade ability. - - balance: Bloodsucker bats now have human runspeed - - balance: Blood cost for vassalizing was almost completely removed, now only taking - tiny amounts of blood to do so. - - balance: Fortitude now gives you burn resistance, just 20% less than brute resistance - - balance: Can no longer gut bloodsuckers - - balance: Bloodsuckers loosing their heart will make the vampire unable to use - their abilities or even regenerateor revive via torpor, you can however regain - your heart if you sleep in a coffin with a heart. - - balance: Stakes now have different properties, the normal stake is fast to stick - in someone, but can fall out on it's own, the burnt one takes longer to be put - in, but doesn't fall out, the silver stake is the slowest to be stuffed in someone's - heart, and is the only stake to be able to cause a Final Death to a sleeping - or dead bloodsucker - - rscdel: Dullahans can't be bloodsuckers since... their head isn't attached - - admin: Bloodsuckers and vassals can now be banned like other antags. - - bugfix: Borers no longer get wasted by ash storms while inside a host - - rscadd: Adds the hemophage-only quirk, Sol weakness - - code_imp: Refactors the sol subsystem so that itself decides if it should run - or not based on if anyone is using it. - - code_imp: Refactors bloodsucker UI elements so that they can function fine outside - a bloodsucker antag datum - - code_imp: bloodsucker_blood_volume, humanity_lost, bloodsucker_level and bloodsucker_level_unspent - are now private variables due to them being used for UI updates, if you need - to change them, use the procs that are written in the autodoc - - code_imp: Quirk species whitelists no longer use bitflags, but use the species - ID's. Easily allowing you to add new whitelists without having to mess around - with making a new bitfield - - bugfix: Ventrue sired bloodsuckers will no longer have a copy of their abilities - - rscadd: Bloodsuckers that start out with no heart will be able to regain one, - but it now properly checks if they have one or not, and disables their abiltiies - accordingly, go into a coffin with a heart if you want to gain one. - - rscadd: Lunge can now take out any organ out of a dead corpse, based on where - you are aiming in the targeting doll, it will still prioritize a heart if aimed - at chest - - bugfix: bloodsucker sol quirk removal is now silent - - bugfix: You can no longer unwrench lair coffins - - bugfix: gohome will no longer render you stuck in a coffin if it cannot close - - bugfix: Malkavians should now spout nonsense less often if you've not lost humantiy - yet - - bugfix: 'Lunge can now actually stun people if you lunge at them from behind. - - fix; You can no longer spam drink from blood bags.' - - code_imp: clan_life now has seconds_per_tick and times_fired - - bugfix: Book of kindred display cases should now spawn properly on TG maps. - - bugfix: Duplicate books of kindred won't spawn on new curators - Azarak: - - admin: administrators can now toggle job playtime exemption by job basis for players - Boviro: - - rscadd: Added butler as assistant title - BurgerB: - - bugfix: Fixes Moonstation Ministation not counting blob tiles. - BurgerBB: - - balance: The RBMK can now handle more power generation before going into meltdown - with upgraded parts, and also generates less power with upgraded parts. - - bugfix: Fixes the RBMK having an infinite meltdown state when safeties trigger - at the same time as a meltdown. - - balance: After 3 Lichdom resurrections, announcements will be made about your - general phylactery location (the area) when you die. Phylactery binding now - requires the object to be at least bulky in size, and it cannot be fireproof, - lava proof, or indestructible. - - rscadd: Adds REAL banhammers send people to the void temporarily (similar to immortality - talisman or void genetic power) on hit. Hitting someone on combat mode with - it sends them to permabrig instead, if they're not already in the permabrig. - - rscdel: Replaces the High Frequency Blade the wizard gets with a REAL banhammer, - and reduces the spell cost from 3 to 2. - - rscadd: Makes Moon Station actually a moon now because people made fun of me. - - bugfix: Hopefully fixes the error handler throwing errors too early. - - bugfix: Fixes early runtime issue with loadouts. - - bugfix: Fixes fake lattice linters when they spawn on lava - - bugfix: Sandstorms on Moon Station are less annoying in terms of notifications - and sound. Adds missing miner GPSs to lockers + table. Fixes typo in Moon Station - plaque. External airlocks to public areas no longer have access. - - rscdel: Removes some over the top abductor victim objectives and adds some new - ones. - - bugfix: Remaps Moon Station's robotics. Fixes some misplaced objects. - - rscdel: Removes Ash Storms from Moon Station Lavaland - - rscdel: Disables Lance Shuttle on Moon Station because it caused the crew to get - stuck on station for 5 hours once. - - rscdel: Replaces the Meteor Shuttle with THE CUBE. It's an emag only emergency - shuttle that is literally just a 16x16 cube with some engines on it. - - balance: Adds Sex holographic barriers to warn people that there is sex in the - next room. It doesn't block air or movement, but it does warn people, and knowing - is half the battle. They can be purchased in the LustWish under the premium - section. - - bugfix: Fixes planetary atmos getting created when turfs inside the station are - destroyed. - - bugfix: Fixes some Moon Station bugs, such as the funny engineering bridge access - bug and a lack of cigarette/coffee vendors. - - bugfix: Fixes Moonstation radstorms affecting some places it's not supposed to. - - rscdel: Limits Powersinks + Crab-17 purchases to once each per traitor per round. - - rscadd: Adds Ashwalkers to Moonstation - - bugfix: Fixes traitor announcer double-sanitizing. - - rscdel: Removes Xeno Organs from Roundstart Xenomorph Hybrids. They no longer - have plasma vessels, resin spinners, or hive nodes. - - bugfix: Fixes missing telecomms wire in Moonstation - - bugfix: Fixes an atmos oversight with the Voxbox on Moonstation that can lead - to superheated distro. - - rscadd: Assigns a bunch of code levels for ERT that didn't have it or I thought - should have a different one. The changes itself can be seen in the file. - - bugfix: The default code for any ERT is now "Green" so it will no longer show - a missing word when calling ERT. - - bugfix: Fixes various Moon Station issues. - - qol: Allows Ashwalkers to Breathe on Station - - bugfix: Fixes a few moonstation bugs. - - bugfix: Atmos optimization. - - bugfix: Oh Hi Daniel shuttle no longer throws. - - balance: Reworks the Gifted quirk and just gives everyone 6 free quirk points. - - bugfix: Fixes Moonstation Xenobiology Shield Walls - - rscdel: Disables Station Blackout and Random Machine Languages Station Traits - - rscadd: Adds Moonstation public mining. - - bugfix: Fixes various Moonstation bugs. - - balance: Xenos can only devour mobs that have a ventcrawler trait (Monkeys, most - Simplemobs), assuming all other checks have passed. - - balance: Heads can only be dismembered if they have a critical-tier (Compound) - fracture. If a head was supposed to be dismembered from a blow, a compound fracture - will be applied. +2024-04-21: CliffracerX: - rscadd: you can mount Mk. II Hyposprays onto the underside of Hypospray Kits & quickdraw them @@ -572,212 +412,139 @@ - admin: icspawning supports quirks & loadout items now - admin: bluespace technician RPED has been significantly upgraded - bugfix: hotfix for loadout wallets not filling properly - Erol509: - - rscadd: RB-MK2 now has its own tgui panel. - - rscadd: Added the icewalker areas to the radstorm protected areas. - - bugfix: Bloodsucker braincheck was missing a null check causing runetimes, its - been fixed. - - rscadd: Added back TEG to techwebs and engineering protolathe - - image: Changed TEG sprites from YogStation. Credits to original author. - EspeciallyStrange: - - bugfix: IDMA donor clothing being improperly offsetted and not correctly - Iamgoofball: - - rscadd: Re-enables the Galactic Materials Market as it's been fixed upstream. - IgiariValkyr: - - config: Relocked some donator items from Skyrat on request - - config: Relocks another skyrat donor item per request. - - rscadd: New Traitor Item (10TC) - Portable Listening Advanced Post - Jinshee: - - rscadd: Added rattlesnake tail - Kegdo: - - rscadd: 'more markings: Chestplate, hip, elbow, shoulder, glove, sleeve, sock, - longsock, vertical stripe, fangs, lips, facemask, facedisc.' - LT3: - - balance: Rebalanced alcohol intoxication effects. A unit of alcohol will now produce - the same intoxication regardless if you chug it all at once or sip it over a - few minutes - - qol: Airlocks don't flash constantly on engineering override, override/overlay - added for fire alarm - - bugfix: Airlock lighting should no longer render on top of player characters - - bugfix: Airlock emissives no longer overlap firedoors - - bugfix: Fixed missing overlays on various airlock types - - bugfix: Fixed status display for epsilon alert - - bugfix: Fixed fire alarm for epsilon alert - - bugfix: Fixed ineligible airlocks from receiving engineering override when activated - from the communications console - - bugfix: Various airlock/firelock overlay fixes - - code_imp: Parts of firelock code updated to parity with TG - - image: Added Moonstation specific tram sprites - - bugfix: Fixed Moonstation references to Tramstation's tram - - qol: Catbox and Imgbox are now supported hosting services for headshots - - qol: 'New moodlet: Status if you''re still processing alcohol you''ve drank previously - (and getting more drunk)' - - qol: 'New moodlet: Current drunk level' - - bugfix: Light drinker quirk should no longer floor you near instantly +2024-04-24: Majkl-J: - - rscadd: Ghosts without clients get sent back into the menu after a while. - - bugfix: NSFW Headshots no longer override regular ones - - bugfix: 'lathes now use moderate power for printing operations /:cl:' - - code_imp: Bubber modular greyscale files permitted - - bugfix: you can now rightclick to flag in minesweeper - - bugfix: Void raptor now has the secmed locker - - rscadd: Zombie can now have hair - - bugfix: Secmeds no longer limit a few items to themselves only - - bugfix: Dauntless frames are no longer broken - - bugfix: False walls appear again - - balance: Bodyless ghosts and ghostroles can no longer transfervote - - refactor: Added support for vote mob conditions - - balance: Reagent weapons now get damaged upon reagent transfer - - balance: Imbuing once again needs actual skill - - bugfix: Minesweeper now properly gives moodlets - - bugfix: teshvali no longer have you wear human sprites - - image: New rockfruit sprites - - code_imp: Modularized hydroponics - Makeshift-coder: - - rscadd: adds an unpacked colony fabricator - - rscadd: replaces the four bluespace beakers on a table with a bluespace beaker - box for ease of access - - rscdel: Removed a single sink to put the unpacked fabricator on it - Odairu: - - config: changes law 2 wording - PhazeJump: - - rscadd: Added Harpy (large) wings - ReturnToZender: - - balance: NTR's ACCESS_CREMATORIUM replaced with ACCESS_SERVICE - - rscadd: Assistants on-station may be pleased to hear that they can now wear Head - of Staff pet collars again. ...Again. - - rscadd: Nanotrasen has deemed it fit to order an upgrade to all Consultant offices - on stations in the Spinward Sector. Check them out! - - rscdel: Donors' graceful trenchcoat - - rscadd: NTC offices have had their carpet changed out to something less over-the-top. - The windows have been expanded as well. - ReturnToZender (Writing), LT3, Waterpig (Code assistance): - - bugfix: If you have no custom species set, it will now show your default description. - ReturnToZender (code): - - bugfix: Character Directory sorting now works on all variables. - - bugfix: autopunctuation respects prefs again - - qol: Advert settings have been moved to a new category, ADVERT. - - rscadd: Character directory now has a search function on the name var. - - rscadd: Character directory now shows on the Main Menu under the Crew Manifest. - - rscadd: Character directory now has a randomizer, which will open a random player's - flavor text when clicked. Click if you dare. - - rscadd: F-list headshots are now accepted - - rscadd: Kiboko 25mm to Armory tab - - rscadd: Mini E-Gun to goodies and armory - - balance: Reduces the cost of the d'Elite rifle as it is more of a side-grade now - ReturnToZender (quirk code), TeshariEnjoer (original PR): - - rscadd: New positive trait, featherweight. Allows you to be picked up instead - of fireman's carried. This dipshit yours? - Shayoki: - - rscadd: Adds Boxstation - - rscadd: Players can now choose a voice for their characters. - - sound: Added a lot of 'borrowed' sounds to use as voices. - - admin: Admins can globally disable Bloopers - Spicelet: - - rscadd: new dogborg shirt - StrangeWeirdKitten: - - rscdel: Removes the Dauntless cameras - - rscdel: Removes the blast cannon from the traitor scientist uplink - - rscdel: Removes Dauntless self destruct and dense rock surrounding the base - - balance: Dauntless exterior turrets shoot fauna, not people - - config: Removes Akula Lore protection (Allows edit to species) - - bugfix: Humanoid and Hemophage sprites no longer have base skin tone issues. Added - human greyscale sprites. - - bugfix: Colossus will properly deaggro when you lose - - balance: But colossus bolts will gut you as a consiquence - - image: Removes the east and west sprite on the Lips bodymarking - - rscadd: Sauna survival pods. Found in mining vendor and occasionally maintenance - Swiftfeather: - - admin: Will no longer receive supermatter ate a pipe spam in the log. - - rscdel: Removed gun safeties. - Sylphet: - - rscadd: adds lunchboxes that hold food and drinks to the loadout - - image: added lunchbox sprites - - balance: scrubbers do not overflow with carpet and rainbow stuff anymore - Tupina: - - balance: Energy weapons can now fire roughly 1.3x more lasers per charge across - the board. - VrazzleDazzle: - - rscadd: Scrying Lens Disks are now available in the loadout. - - qol: The ashwalkers' ashen necklaces are now fireproof. - - rscdel: Death bolts no longer dust you on death. - - rscadd: Six new PKA variants, now in a mining vendor near you. - - rscdel: Prybars are no longer available in the Rapid Construction Fabricator. - Vynzill: - - rscadd: Added more perfumes to loadout. - YakumoChen: - - balance: Xeno Hybrids take normal heat damage, again. - Yanziko: - - balance: pet owner is free + - bugfix: Basicmob xenos no longer die to lack of heating + SkyratBot: + - balance: The Bioscrambler will now actively attempt to get closer to living targets + rather than chilling in a closet nobody goes into (unless you trap it in a containment + field). + - balance: Because it can now travel through walls, the Bioscrambler will no longer + transform you THROUGH walls. + TreePizza: + - rscadd: Added a fax machine to the Tarkon bridge, as well as it's unique contact + for Tarkon TB (Top Brass). + - rscadd: The station can now fax the Tarkon bridge. The Ensign can now finally + do their job without having to leave their chair. + - rscadd: Added an Ectosniffer to the science lab so ghosts may now request a brain + to possess. + - rscadd: ~1 "hidden" Xenoplush for Monophobia characters.~ Goodnight sweet prince + you were too good for this world. + - rscadd: Added a light to the freezer and an additional one to the kitchen. + - bugfix: Added that awkwardly missing window to the top airlock and deleted the + equally awkward single disposal pipe that was underneath it. + - bugfix: 'Moved the glowing resin in the cargo_warehouse variation (the infested + one) so that it is no longer under the glass wall. + + ### Charlie:' + - qol: 'Charlie pods now have pref and loadout spawning. + + :cl:' +2024-04-26: + Jacquerel and Melbert: + - rscadd: A new achievement for moving a boulder from one place to another, at great + effort. + - balance: Hauling a boulder around makes you move slower, as it does when dragging + it. + Majkl-J: + - bugfix: Medicells now correctly use power + - bugfix: MCRs now correctly use power + - bugfix: Infinite powercells now have infinite power that's useful and not 2500 + Joules + - qol: slimes will stay active without needing any one to watch over + - code_imp: The way mobs idle has been refactored, please report any issues with + non-reactive mobs + Melbert: + - bugfix: Playing Cards memory now reads better + SkyratBot: + - bugfix: Fixes AI lag by re-adding idle mode to all AI that was lost with the simple + mob to basic mob conversion. + - bugfix: AI controllers with no clients around for 14 tiles will move into idle + mode and stop planning or acting. + - bugfix: AI controllers will now record how much time was spent on planning or + un-idling AI controllers. + - bugfix: The rebar crossbows now properly loosen their bowstring upon firing. + - balance: Longfall modules no logner stun you when they activate. + - balance: Falling from a height greater than one z-level while using the longfall + module will still stagger you. + - bugfix: The plasma flower modsuit core now actually contains a reasonable quantity + of power. +2024-04-27: aKromatopzia: - - rscadd: Unamored versions of the syndicate utility uniforms & half-mask - - bugfix: icecats and ashliz can spawn on the ghost cafe. - - image: icon was wrongly offset for cybernetic digitigrade right legs + - rscadd: Chaplains can be "Clerics" +2024-04-28: + BurgerBB: + - rscadd: Moonstation Upstream Merge and Bonuses + - bugfix: Fixes assistants always spawning at the Interlink roundstart. + - rscadd: Improves Moonstation Disposals + Fixes missing wires for Medical Storage + and NTRep office. + Iamgoofball: + - balance: Takes the ashwalker translation necklace out of the loadout; ashwalker + translation is supposed to be rare/craftable with resource/Curator, not a roundstart + thing any crewmember can have. + IgiariValkyr: + - rscadd: Latex Heels to loadout + - qol: Filing cabinets in the Interlink office are now actually stacked together + - bugfix: PLAP capsule now has the colors actually described in the description + Majkl-J: + - bugfix: Fixes horrendous ui design + - bugfix: Synth recharging in mechchargers is now fixed + - bugfix: Crank cell can now be cranked for 1MJ of energy instead of 100J. How a + human manages to pull that off shall not be discussed + Melbert: + - qol: Tuberculosis makes you cough more + - qol: Nicotine Addiciton makes you cough less + - qol: Medicine Addiction maybe makes you cough more, maybe makes you cough less + - rscadd: Being deafnened from a loud sound (flashbang, explosions) will now force + people not naturally deaf to shout + - rscadd: Ear damage multiplier now only applies to taking damage, not healing damage, + meaning Felinids (who take 2x the ear damage) will no longer heal ear damage + 2x faster. + - refactor: Ears have been refactored slightly, ear deafness should now update more + snappily + PhazeJump: + - rscadd: 'wings: Moth (Bluespace)' + - rscadd: 'wings: Moth (Strawberry)' + - rscadd: 'wings: Moth (Clockwork)' + Rhials: + - qol: Water tiles now extinguish fires on items and people. + SkyratBot: + - bugfix: basic bots no longer start with all access + - bugfix: being revived with a cyber-heart now properly restarts the cyber heart + - rscadd: miners can now purchase grapple guns + - bugfix: Fixes clipping in the ESC menu between buttons and long station names. + - bugfix: brimbeams no longer make a cog appear above the mob + - bugfix: cooling and anti-disruption RCD upgrades can now be printed in ancient + protolathes + - qol: There's a bit more user feedback when it comes to attempting to handcuff + someone. + StrangeWeirdKitten: + - balance: Abductor sleep is 30 seconds instead of 2 minutes + Swiftfeather: + - rscadd: Blind crew are no longer barred from being heads of staff (except HoS). + - balance: Makes bluespace crystal teleportation take time. + - code_imp: The way mobs idle has been refactored, please report any issues with + non-reactive mobs + VexingRaven: + - bugfix: The debug box no longer spills its contents everywhere + VrazzleDazzle: + - image: Added a new UI theme, Blue-98! + - rscdel: The PKA variants have been temporarily pruned due to a licensing issue + with Kahraman Industries. destrucktoid: - - bugfix: Syndicate/Ninja Borg Restorative Nanites now heal Slimepeople just as - well as they do other people. - - rscadd: Borers back in uplink - - bugfix: Slimeperson Clockwork Cultists now heal toxins from the prosperity prism - properly. - - balance: Ventrue cannot benefit from bloodbags if their blood exceeds BLOOD_VOLUME_NORMAL - - refactor: Changed reac_volume to use AddBloodVolume() for consistency reasons - iskawhiskers: - - image: added monster2_head, monster3_head, weight2_chest_m, weight2_chest_f - nevimer: - - balance: you now hug and pat lightgeists - - admin: added public log folder, and logging. - - balance: contractor and ninja modsuits have DNA locked microbombs - nikothedude: - - bugfix: Death degradation properly DNRs - - bugfix: DNR icon has been restored - - rscadd: Robos now have a pamphlet in their bag that tells them tips and tricks - on how treat synth wounds - - 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 - - rscadd: You can now set your characters height + - balance: Bloodsuckers can no longer kill or hurt people by drinking from them + without at least a passive grab. + grungussuss: + - bugfix: fixed being able to install multiple of the same upgrade to medical cyborgs + kaylexis: + - rscadd: Adds Plant Gene disk to biogen pixelkitty286: - - rscadd: +Peacekeeper cat borg sprites, Spider clan cat borg sprites, Engineer - cat borg refreshed sprites - - bugfix: Cat cyborg panels not working - - image: +Peacekeeper cat borg sprites, Spider clan cat borg sprites, Engineer cat - borg refreshed sprites - - code_imp: -Duplicate code - - rscadd: Added night vision and cold resistance to tajara with their respective - debuffs and gave them sensitive hearing. tajara own meat type and cat animal - hide when gibed. Cat like grace to tajara. - - rscadd: Added modular tajaran.dm, siikmaas.dm, and meatslab.dmi - - qol: The Tajara DLC. - - balance: rebalanced how the Tajaran species works. - - image: added a Tajaran ass picture. Added adhomian_meat (Credit goes to Aurora.3 - on the sprite) - - spellcheck: Corrected siik'tajr to be siik'maas. - - code_imp: modular code for tajaran species changes. - - refactor: Does refactoring Tajara as a species count? - projectkepler-ru: - - rscadd: Marketable IDMA Plushie, selectable as ironmoon tajaran plushie - - rscadd: Contract from Colt has been secured with NT and now we can buy m1911 - - image: icon updated for the reshi revolver - - balance: Colt reevaluated their contract, the M1911 is cheaper now + - rscadd: The PKA variants. tmyqlfpir: - - qol: Tweak layout of Dauntless kitchen, dorms and medbay - - rscadd: Slapping glass tables have a 15% chance (cursed 30%) of breaking on 3rd - slap - - rscadd: Adds cargo ordering functionality for dauntless base - - rscadd: Add bitden to dauntless brig area - - rscadd: Add door lock to dauntless restroom, and various map tweaks - - rscadd: Dauntless - Add exterior cameras to dauntless, removed many interior ones - - bugfix: Dauntless - Removed incorrectly placed decals under hull objects and tweaked - brig/dorms - - balance: Interdyne powerator is now maxcapped to 1MW - - rscadd: Dauntless - Added new bounty pad and bounty console - - rscadd: Dauntless - Added new produce order console - xXPawnStarrXx: - - image: added GAGS versions of command stripper outfits. - - code_imp: removed donator requirement from loadout flowers. - - qol: made DeForest medipens refillable. - - rscadd: Blood filtering now restores toxins. - - bugfix: korve skinned advanced tools being invisible. - - qol: made endurogrow boost lifespan. + - qol: Various tweaks to Dauntless service and medical + - rscadd: Add new camera kill switches to the Dauntless + - rscadd: Add (non-spawned) space version of Dauntless + - rscadd: Add new storage room to Dauntless + - balance: Dauntless cyborgs will have their cameras automatically removed + - balance: Interdyne Powerator has 2x efficiency + - rscadd: Created Interdyne injectors to assign non-spawned crew as Syndicate faction diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi index 12e3ce9f7d5..fd7bee8ed60 100644 Binary files a/icons/effects/beam.dmi and b/icons/effects/beam.dmi differ diff --git a/icons/hud/radial.dmi b/icons/hud/radial.dmi index 90813b4d7d2..e4a1693fb57 100644 Binary files a/icons/hud/radial.dmi and b/icons/hud/radial.dmi differ diff --git a/icons/mob/clothing/head/hats.dmi b/icons/mob/clothing/head/hats.dmi index bdf9980b9f2..8ed78b1c161 100644 Binary files a/icons/mob/clothing/head/hats.dmi and b/icons/mob/clothing/head/hats.dmi differ diff --git a/icons/mob/clothing/head/helmet.dmi b/icons/mob/clothing/head/helmet.dmi index 49edcf8422f..317edb56796 100644 Binary files a/icons/mob/clothing/head/helmet.dmi and b/icons/mob/clothing/head/helmet.dmi differ diff --git a/icons/mob/clothing/suits/armor.dmi b/icons/mob/clothing/suits/armor.dmi index be2ba8f3730..90be12b694a 100644 Binary files a/icons/mob/clothing/suits/armor.dmi and b/icons/mob/clothing/suits/armor.dmi differ diff --git a/icons/mob/inhands/clothing/hats_lefthand.dmi b/icons/mob/inhands/clothing/hats_lefthand.dmi index 191c85cf482..1d6461fb39d 100644 Binary files a/icons/mob/inhands/clothing/hats_lefthand.dmi and b/icons/mob/inhands/clothing/hats_lefthand.dmi differ diff --git a/icons/mob/inhands/clothing/hats_righthand.dmi b/icons/mob/inhands/clothing/hats_righthand.dmi index 8038e7474ee..4d9710bf901 100644 Binary files a/icons/mob/inhands/clothing/hats_righthand.dmi and b/icons/mob/inhands/clothing/hats_righthand.dmi differ diff --git a/icons/mob/inhands/clothing/suits_lefthand.dmi b/icons/mob/inhands/clothing/suits_lefthand.dmi index a43756d743a..02b1e2cbff2 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 da837fdd857..7dd047b7345 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/balloons_lefthand.dmi b/icons/mob/inhands/items/balloons_lefthand.dmi index cf51ac313e2..7fed45fc590 100644 Binary files a/icons/mob/inhands/items/balloons_lefthand.dmi and b/icons/mob/inhands/items/balloons_lefthand.dmi differ diff --git a/icons/mob/inhands/items/balloons_righthand.dmi b/icons/mob/inhands/items/balloons_righthand.dmi index 606f2007fd7..c1856b2260b 100644 Binary files a/icons/mob/inhands/items/balloons_righthand.dmi and b/icons/mob/inhands/items/balloons_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/hammers_lefthand.dmi b/icons/mob/inhands/weapons/hammers_lefthand.dmi index 7f6985e1de5..5856bd8b0f8 100644 Binary files a/icons/mob/inhands/weapons/hammers_lefthand.dmi and b/icons/mob/inhands/weapons/hammers_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/hammers_righthand.dmi b/icons/mob/inhands/weapons/hammers_righthand.dmi index 2dd4f4b64c5..c6e8a0215ea 100644 Binary files a/icons/mob/inhands/weapons/hammers_righthand.dmi and b/icons/mob/inhands/weapons/hammers_righthand.dmi differ diff --git a/icons/obj/clothing/head/hats.dmi b/icons/obj/clothing/head/hats.dmi index 14b0fdf8b4c..938090ec82e 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/head/helmet.dmi b/icons/obj/clothing/head/helmet.dmi index 94d11e6b820..3bea00dcdc3 100644 Binary files a/icons/obj/clothing/head/helmet.dmi and b/icons/obj/clothing/head/helmet.dmi differ diff --git a/icons/obj/clothing/suits/armor.dmi b/icons/obj/clothing/suits/armor.dmi index 5ff4e25df86..4fb7248dbd8 100644 Binary files a/icons/obj/clothing/suits/armor.dmi and b/icons/obj/clothing/suits/armor.dmi differ diff --git a/icons/obj/machines/computer.dmi b/icons/obj/machines/computer.dmi index f8fb31c9ba0..9fcc46bf9b4 100644 Binary files a/icons/obj/machines/computer.dmi and b/icons/obj/machines/computer.dmi differ diff --git a/icons/obj/medical/chemical.dmi b/icons/obj/medical/chemical.dmi index b4b26e4f848..84dfd01d2d4 100644 Binary files a/icons/obj/medical/chemical.dmi and b/icons/obj/medical/chemical.dmi differ diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi index ca97d91561b..1f6393a8c51 100644 Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ diff --git a/icons/obj/storage/box.dmi b/icons/obj/storage/box.dmi index 8b037860144..c0a327d7df6 100644 Binary files a/icons/obj/storage/box.dmi and b/icons/obj/storage/box.dmi differ diff --git a/icons/obj/structures.dmi b/icons/obj/structures.dmi index 85367e1c47b..1bb6689becf 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 4e26f75aa99..2c2aae54de3 100644 Binary files a/icons/obj/tiles.dmi and b/icons/obj/tiles.dmi differ diff --git a/icons/obj/toys/balloons.dmi b/icons/obj/toys/balloons.dmi index 0ed6f471bfb..96afdaea2c0 100644 Binary files a/icons/obj/toys/balloons.dmi and b/icons/obj/toys/balloons.dmi differ diff --git a/icons/obj/toys/toy.dmi b/icons/obj/toys/toy.dmi index 9ac61738fad..f53b0781f6e 100644 Binary files a/icons/obj/toys/toy.dmi and b/icons/obj/toys/toy.dmi differ diff --git a/icons/obj/weapons/guns/projectiles.dmi b/icons/obj/weapons/guns/projectiles.dmi index 11b9af13a2c..b2579d58bf2 100644 Binary files a/icons/obj/weapons/guns/projectiles.dmi and b/icons/obj/weapons/guns/projectiles.dmi differ diff --git a/icons/obj/weapons/hammer.dmi b/icons/obj/weapons/hammer.dmi index 965fd0b37ef..751e6267798 100644 Binary files a/icons/obj/weapons/hammer.dmi and b/icons/obj/weapons/hammer.dmi differ diff --git a/icons/turf/composite.dmi b/icons/turf/composite.dmi index 7bb2d471788..a40c4121d25 100644 Binary files a/icons/turf/composite.dmi and b/icons/turf/composite.dmi differ diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi index 89b4876c0ce..03dd1bcbfc3 100644 Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ diff --git a/icons/ui_icons/arcade/fireplace.png b/icons/ui_icons/arcade/fireplace.png new file mode 100644 index 00000000000..080cadbebf0 Binary files /dev/null and b/icons/ui_icons/arcade/fireplace.png differ diff --git a/icons/ui_icons/arcade/shopkeeper.png b/icons/ui_icons/arcade/shopkeeper.png new file mode 100644 index 00000000000..e5eca14d856 Binary files /dev/null and b/icons/ui_icons/arcade/shopkeeper.png differ diff --git a/modular_skyrat/master_files/code/datums/traits/neutral.dm b/modular_skyrat/master_files/code/datums/traits/neutral.dm index 09020832304..2e66d536685 100644 --- a/modular_skyrat/master_files/code/datums/traits/neutral.dm +++ b/modular_skyrat/master_files/code/datums/traits/neutral.dm @@ -205,7 +205,7 @@ GLOBAL_VAR_INIT(DNR_trait_overlay, generate_DNR_trait_overlay()) ..() icon_state = "joker" -/obj/item/paper/joker/AltClick(mob/living/carbon/user, obj/item/card) +/obj/item/paper/joker/click_alt(mob/user) var/list/datum/paper_input/old_raw_text_inputs = raw_text_inputs var/list/datum/paper_stamp/old_raw_stamp_data = raw_stamp_data var/list/datum/paper_stamp/old_raw_field_input_data = raw_field_input_data @@ -225,6 +225,7 @@ GLOBAL_VAR_INIT(DNR_trait_overlay, generate_DNR_trait_overlay()) update_static_data() balloon_alert(user, "card flipped") + return CLICK_ACTION_SUCCESS /datum/quirk/feline_aspect name = "Feline Traits" diff --git a/modular_skyrat/master_files/code/game/machinery/doors/firedoor.dm b/modular_skyrat/master_files/code/game/machinery/doors/firedoor.dm index c37193a6fe8..1f73f708edf 100644 --- a/modular_skyrat/master_files/code/game/machinery/doors/firedoor.dm +++ b/modular_skyrat/master_files/code/game/machinery/doors/firedoor.dm @@ -1,7 +1,4 @@ -/obj/machinery/door/firedoor/AltClick(mob/user) - . = ..() - if(!user.can_perform_action(src)) - return +/obj/machinery/door/firedoor/click_alt(mob/user) try_manual_override(user) /obj/machinery/door/firedoor/examine(mob/user) diff --git a/modular_skyrat/master_files/code/game/objects/items/stacks/sheets/sheet_types.dm b/modular_skyrat/master_files/code/game/objects/items/stacks/sheets/sheet_types.dm index 93cd93f1a50..c399c7272d5 100644 --- a/modular_skyrat/master_files/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/modular_skyrat/master_files/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -78,10 +78,10 @@ GLOBAL_LIST_INIT(skyrat_wood_recipes, list( new/datum/stack_recipe("large wooden mortar", /obj/structure/large_mortar, 10, time = 3 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_TOOLS), new/datum/stack_recipe("wooden cutting board", /obj/item/cutting_board, 5, time = 2 SECONDS, check_density = FALSE, category = CAT_TOOLS), new/datum/stack_recipe("wooden shelf", /obj/structure/rack/wooden, 2, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = FALSE, category = CAT_STRUCTURE), - new/datum/stack_recipe("seed shelf", /obj/machinery/smartfridge/seedshelf, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE), - new/datum/stack_recipe("produce bin", /obj/machinery/smartfridge/producebin, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE), - new/datum/stack_recipe("produce display", /obj/machinery/smartfridge/producedisplay, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE), - new/datum/stack_recipe("ration shelf", /obj/machinery/smartfridge/rationshelf, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE), + new/datum/stack_recipe("seed shelf", /obj/machinery/smartfridge/wooden/seed_shelf, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE), + new/datum/stack_recipe("produce bin", /obj/machinery/smartfridge/wooden/produce_bin, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE), + new/datum/stack_recipe("produce display", /obj/machinery/smartfridge/wooden/produce_display, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE), + new/datum/stack_recipe("ration shelf", /obj/machinery/smartfridge/wooden/ration_shelf, 10, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE), new/datum/stack_recipe("storage barrel", /obj/structure/closet/crate/wooden/storage_barrel, 4, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = FALSE, category = CAT_STRUCTURE), new/datum/stack_recipe("worm barrel", /obj/structure/wormfarm, 5, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_TOOLS), new/datum/stack_recipe("gutlunch trough", /obj/structure/ore_container/gutlunch_trough, 5, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_STRUCTURE), diff --git a/modular_skyrat/master_files/code/game/objects/structures/towel_bins.dm b/modular_skyrat/master_files/code/game/objects/structures/towel_bins.dm index adf8066b6e3..21996590ed4 100644 --- a/modular_skyrat/master_files/code/game/objects/structures/towel_bins.dm +++ b/modular_skyrat/master_files/code/game/objects/structures/towel_bins.dm @@ -48,9 +48,6 @@ /obj/structure/towel_bin/screwdriver_act(mob/living/user, obj/item/tool) - if(obj_flags & NO_DECONSTRUCTION) - return FALSE - if(amount) to_chat(user, span_warning("[src] must be empty first!")) return ITEM_INTERACT_SUCCESS @@ -60,7 +57,8 @@ new /obj/item/stack/rods(loc, 2) qdel(src) return ITEM_INTERACT_SUCCESS - + if(!(obj_flags & NO_DEBRIS_AFTER_DECONSTRUCTION)) + new /obj/item/stack/rods(loc, 2) /obj/structure/towel_bin/wrench_act(mob/living/user, obj/item/tool) . = ..() diff --git a/modular_skyrat/master_files/code/modules/admin/admin.dm b/modular_skyrat/master_files/code/modules/admin/admin.dm index 86f86bc7e12..91afc0def67 100644 --- a/modular_skyrat/master_files/code/modules/admin/admin.dm +++ b/modular_skyrat/master_files/code/modules/admin/admin.dm @@ -1,9 +1,6 @@ GLOBAL_VAR_INIT(dchat_allowed, TRUE) -/datum/admins/proc/toggledchat() - set category = "Server" - set desc = "Toggle dis bitch" - set name = "Toggle Dead Chat" +ADMIN_VERB(toggledchat, R_ADMIN, "Toggle Dead Chat", "Toggle dis bitch.", ADMIN_CATEGORY_SERVER) toggle_dchat() log_admin("[key_name(usr)] toggled dead chat.") message_admins("[key_name_admin(usr)] toggled dead chat.") @@ -66,12 +63,12 @@ GLOBAL_VAR_INIT(dchat_allowed, TRUE) /datum/admin_help/proc/convert_to_mentorhelp(key_name = key_name_admin(usr)) if(state != AHELP_ACTIVE) return FALSE - + if(handler && handler != usr.ckey) var/response = tgui_alert(usr, "This ticket is already being handled by [handler]. Do you want to continue?", "Ticket already assigned", list("Yes", "No")) if(!response || response == "No") return FALSE - + add_verb(initiator, /client/verb/mentorhelp) // Way to override mentorhelp cooldown. to_chat(initiator, span_adminhelp("Your ticket was converted to Mentorhelp")) diff --git a/modular_skyrat/master_files/code/modules/clothing/towels.dm b/modular_skyrat/master_files/code/modules/clothing/towels.dm index a8f2199a619..4add82d6a41 100644 --- a/modular_skyrat/master_files/code/modules/clothing/towels.dm +++ b/modular_skyrat/master_files/code/modules/clothing/towels.dm @@ -236,17 +236,12 @@ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN -/obj/item/towel/AltClick(mob/user) - . = ..() - - if(. == FALSE) - return - +/obj/item/towel/click_alt(mob/user) if(!(shape == TOWEL_FULL || shape == TOWEL_WAIST)) - return FALSE + return CLICK_ACTION_BLOCKING if(!ishuman(user)) - return FALSE + return CLICK_ACTION_BLOCKING var/mob/living/carbon/human/towel_user = user var/worn = towel_user.wear_suit == src @@ -258,6 +253,7 @@ return to_chat(user, span_notice(shape == TOWEL_FULL ? "You raise \the [src] over your [shape]." : "You lower \the [src] down to your [shape].")) + return CLICK_ACTION_SUCCESS /obj/item/towel/CtrlClick(mob/user) diff --git a/modular_skyrat/master_files/code/modules/reagents/reagent_containers.dm b/modular_skyrat/master_files/code/modules/reagents/reagent_containers.dm index c4f79461fd9..eb187857d7b 100644 --- a/modular_skyrat/master_files/code/modules/reagents/reagent_containers.dm +++ b/modular_skyrat/master_files/code/modules/reagents/reagent_containers.dm @@ -1,5 +1,4 @@ -/obj/item/reagent_containers/AltClick(mob/user) - . = ..() +/obj/item/reagent_containers/click_alt(mob/living/user) if(length(possible_transfer_amounts) <= 2) // If there's only two choices, just swap between them. change_transfer_amount(user, FORWARD) return diff --git a/modular_skyrat/modules/SiliconQoL/code/_onclick.dm b/modular_skyrat/modules/SiliconQoL/code/_onclick.dm index 9589c8d40ab..9c926537895 100644 --- a/modular_skyrat/modules/SiliconQoL/code/_onclick.dm +++ b/modular_skyrat/modules/SiliconQoL/code/_onclick.dm @@ -4,7 +4,7 @@ /mob/living/silicon/ai/CtrlShiftClickOn(atom/A) if(isturf(A)) - var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A + var/obj/machinery/door/airlock/airlock = locate() in A if(airlock) airlock.AICtrlShiftClick(src) else @@ -12,7 +12,7 @@ /mob/living/silicon/ai/ShiftClickOn(atom/A) if(isturf(A)) - var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A + var/obj/machinery/door/airlock/airlock = locate() in A if(airlock) airlock.AIShiftClick(src) else @@ -21,19 +21,19 @@ /mob/living/silicon/ai/CtrlClickOn(atom/A) if(isturf(A)) - var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A + var/obj/machinery/door/airlock/airlock = locate() in A if(airlock) airlock.AICtrlClick(src) else A.AICtrlClick(src) -/mob/living/silicon/ai/AltClickOn(atom/A) - if(isturf(A)) - var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A - if(airlock) - airlock.AIAltClick(src) - else - A.AIAltClick(src) +/turf/ai_click_alt(mob/living/silicon/ai/user) + var/obj/machinery/door/airlock/airlock = locate() in src + if(airlock) + airlock.ai_click_alt(user) + return + return ..() + /atom/proc/AIExamine() // Used for AI specific examines .Currently only employed to stop door examines. usr.examinate(src) @@ -45,10 +45,10 @@ /mob/living/silicon/ai/ClickOn(atom/A, params) ..() var/list/modifiers = params2list(params) - if(isturf(A)&&(!modifiers)) // Have to check for modifiers. - var/obj/machinery/door/firedoor/TheDoor = locate(/obj/machinery/door/firedoor) in A - if(TheDoor) - TheDoor.attack_ai(usr) + if(isturf(A) && !modifiers) // Have to check for modifiers. + var/obj/machinery/door/firedoor/the_door = locate() in A + if(the_door) + the_door.attack_ai(usr) /* * CYBORG CHANGES @@ -56,7 +56,7 @@ /mob/living/silicon/robot/CtrlShiftClickOn(atom/A) if(isturf(A)) - var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A // Skyrat edit + var/obj/machinery/door/airlock/airlock = locate() in A if(airlock) airlock.BorgCtrlShiftClick(src) else @@ -64,7 +64,7 @@ /mob/living/silicon/robot/ShiftClickOn(atom/A) if(isturf(A)) - var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A // Skyrat edit + var/obj/machinery/door/airlock/airlock = locate() in A if(airlock) airlock.BorgShiftClick(src) else @@ -72,16 +72,15 @@ /mob/living/silicon/robot/CtrlClickOn(atom/A) if(isturf(A)) - var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A // Skyrat edit + var/obj/machinery/door/airlock/airlock = locate() in A if(airlock) airlock.BorgCtrlClick(src) else A.BorgCtrlClick(src) // End of skyrat edit -/mob/living/silicon/robot/AltClickOn(atom/A) - if(isturf(A)) - var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in A // Skyrat edit - if(airlock) - airlock.BorgAltClick(src) - else - A.BorgAltClick(src) +/turf/borg_click_alt(mob/living/silicon/robot/user) + var/obj/machinery/door/airlock/airlock = locate() in src + if(airlock) + airlock.borg_click_alt(user) + return + return ..() diff --git a/modular_skyrat/modules/admin/code/aooc.dm b/modular_skyrat/modules/admin/code/aooc.dm index b679f5c8e0d..b3bfb8be52e 100644 --- a/modular_skyrat/modules/admin/code/aooc.dm +++ b/modular_skyrat/modules/admin/code/aooc.dm @@ -102,9 +102,7 @@ GLOBAL_LIST_EMPTY(ckey_to_aooc_name) var/client/iterated_client = iterated_listener to_chat(iterated_client, span_oocplain("The AOOC channel has been globally [GLOB.aooc_allowed ? "enabled" : "disabled"].")) -/datum/admins/proc/toggleaooc() - set category = "Server" - set name = "Toggle Antag OOC" +ADMIN_VERB(toggleaooc, R_ADMIN, "Toggle Antag OOC", "Toggles Antag OOC.", ADMIN_CATEGORY_SERVER) toggle_aooc() log_admin("[key_name(usr)] toggled Antagonist OOC.") message_admins("[key_name_admin(usr)] toggled Antagonist OOC.") diff --git a/modular_skyrat/modules/admin/code/fix_chat.dm b/modular_skyrat/modules/admin/code/fix_chat.dm index e82c3cf73d7..25649f480b8 100644 --- a/modular_skyrat/modules/admin/code/fix_chat.dm +++ b/modular_skyrat/modules/admin/code/fix_chat.dm @@ -1,6 +1,4 @@ -/client/proc/fix_say() - set name = "Fix say for players" - set category = "Admin" +ADMIN_VERB(fix_say, R_ADMIN, "Fix say", "Fix say for the players.", ADMIN_CATEGORY_MAIN) for(var/player in GLOB.player_list) if(!isnull(player)) continue diff --git a/modular_skyrat/modules/admin/code/loud_say.dm b/modular_skyrat/modules/admin/code/loud_say.dm index 82d73fc3723..15c8c025fc3 100644 --- a/modular_skyrat/modules/admin/code/loud_say.dm +++ b/modular_skyrat/modules/admin/code/loud_say.dm @@ -1,22 +1,16 @@ -/client/proc/cmd_loud_admin_say(msg as text) - set category = "Admin" - set name = "loudAsay" - set hidden = TRUE - if(!check_rights(0)) - return - +ADMIN_VERB(cmd_loud_admin_say, R_NONE, "loudAsay", "Send a message to other admins (loudly).", ADMIN_CATEGORY_MAIN, msg as text) msg = emoji_parse(copytext_char(sanitize(msg), 1, MAX_MESSAGE_LEN)) if(!msg) return msg = emoji_parse(msg) - mob.log_talk(msg, LOG_ASAY) + user.mob.log_talk(msg, LOG_ASAY) - send_asay_to_other_server(ckey, span_command_headset(msg)) + send_asay_to_other_server(user.ckey, span_command_headset(msg)) msg = keywords_lookup(msg) - var/custom_asay_color = (CONFIG_GET(flag/allow_admin_asaycolor) && prefs?.read_preference(/datum/preference/color/asay_color)) ? "" : "" - msg = span_command_headset("ADMIN: [key_name(usr, 1)] [ADMIN_FLW(mob)]: [custom_asay_color][msg][custom_asay_color ? "":null]") + var/custom_asay_color = (CONFIG_GET(flag/allow_admin_asaycolor) && user.mob.client?.prefs?.read_preference(/datum/preference/color/asay_color)) ? "" : "" + msg = span_command_headset("ADMIN: [key_name(user, 1)] [ADMIN_FLW(user.mob)]: [custom_asay_color][msg][custom_asay_color ? "":null]") to_chat(GLOB.admins, type = MESSAGE_TYPE_ADMINCHAT, diff --git a/modular_skyrat/modules/admin/code/player_ranks.dm b/modular_skyrat/modules/admin/code/player_ranks.dm index 6e05a42f7d8..242fe92cccb 100644 --- a/modular_skyrat/modules/admin/code/player_ranks.dm +++ b/modular_skyrat/modules/admin/code/player_ranks.dm @@ -1,11 +1,7 @@ /// The list of the available special player ranks #define SKYRAT_PLAYER_RANKS list("Donator", "Mentor", "Veteran") -/client/proc/manage_player_ranks() - set category = "Admin" - set name = "Manage Player Ranks" - set desc = "Manage who has the special player ranks while the server is running." - +ADMIN_VERB(manage_player_ranks, R_PERMISSIONS, "Manage Player Ranks", "Manage who has the special player ranks while the server is running.", ADMIN_CATEGORY_MAIN) if(!check_rights(R_PERMISSIONS)) return @@ -86,16 +82,8 @@ -/client/proc/migrate_player_ranks() - set category = "Debug" - set name = "Migrate Player Ranks" - set desc = "Individually migrate the various player ranks from their legacy system to the SQL-based one." - - if(!check_rights(R_PERMISSIONS | R_DEBUG | R_SERVER)) - return - - usr.client?.holder.migrate_player_ranks() - +ADMIN_VERB(migrate_player_ranks, R_PERMISSIONS|R_DEBUG|R_SERVER, "Migrate Player Ranks", "Individually migrate the various player ranks from their legacy system to the SQL-based one.", ADMIN_CATEGORY_DEBUG) + user.mob.client?.holder.migrate_player_ranks() /datum/admins/proc/migrate_player_ranks() if(IsAdminAdvancedProcCall()) diff --git a/modular_skyrat/modules/admin/code/sooc.dm b/modular_skyrat/modules/admin/code/sooc.dm index 518e8508f06..4ef6ec8a702 100644 --- a/modular_skyrat/modules/admin/code/sooc.dm +++ b/modular_skyrat/modules/admin/code/sooc.dm @@ -109,9 +109,7 @@ GLOBAL_LIST_EMPTY(ckey_to_sooc_name) var/client/iterated_client = iterated_listener to_chat(iterated_client, span_oocplain("The SOOC channel has been globally [GLOB.sooc_allowed ? "enabled" : "disabled"].")) -/datum/admins/proc/togglesooc() - set category = "Server" - set name = "Toggle Security OOC" +ADMIN_VERB(togglesooc, R_ADMIN, "Toggle Security OOC", "Toggles Security OOC.", ADMIN_CATEGORY_SERVER) toggle_sooc() log_admin("[key_name(usr)] toggled Security OOC.") message_admins("[key_name_admin(usr)] toggled Security OOC.") diff --git a/modular_skyrat/modules/advanced_shuttles/code/shuttles.dm b/modular_skyrat/modules/advanced_shuttles/code/shuttles.dm index 78ffdffd034..ebcbf017b3b 100644 --- a/modular_skyrat/modules/advanced_shuttles/code/shuttles.dm +++ b/modular_skyrat/modules/advanced_shuttles/code/shuttles.dm @@ -27,7 +27,6 @@ return INITIALIZE_HINT_LATELOAD /obj/docking_port/mobile/arrivals_skyrat/LateInitialize() - . = ..() console = get_control_console() /obj/docking_port/mobile/arrivals_skyrat/check() diff --git a/modular_skyrat/modules/aesthetics/flag/code/signs_flags.dm b/modular_skyrat/modules/aesthetics/flag/code/signs_flags.dm index 684ce00919b..db83853d657 100644 --- a/modular_skyrat/modules/aesthetics/flag/code/signs_flags.dm +++ b/modular_skyrat/modules/aesthetics/flag/code/signs_flags.dm @@ -16,7 +16,7 @@ /obj/structure/sign/flag/MouseDrop(over_object, src_location, over_location) . = ..() if(over_object == usr && Adjacent(usr)) - if(!item_flag || src.obj_flags & NO_DECONSTRUCTION) + if(!item_flag || src.obj_flags & NO_DEBRIS_AFTER_DECONSTRUCTION) return if(!usr.can_perform_action(src, NEED_DEXTERITY)) return diff --git a/modular_skyrat/modules/aesthetics/keyed_doors/code/keyed_door.dm b/modular_skyrat/modules/aesthetics/keyed_doors/code/keyed_door.dm index 64e1e5536b7..a0cc10497e2 100644 --- a/modular_skyrat/modules/aesthetics/keyed_doors/code/keyed_door.dm +++ b/modular_skyrat/modules/aesthetics/keyed_doors/code/keyed_door.dm @@ -112,8 +112,8 @@ return FALSE -/obj/machinery/door/airlock/keyed/AIAltClick() - return FALSE +/obj/machinery/door/airlock/keyed/ai_click_alt(mob/living/silicon/ai/user) + return /obj/machinery/door/airlock/keyed/AIShiftClick() @@ -128,7 +128,7 @@ return FALSE -/obj/machinery/door/airlock/keyed/BorgAltClick(mob/living/silicon/robot/user) +/obj/machinery/door/airlock/keyed/borg_click_alt(mob/living/silicon/robot/user) return FALSE diff --git a/modular_skyrat/modules/aesthetics/lightswitch/code/lightswitch.dm b/modular_skyrat/modules/aesthetics/lightswitch/code/lightswitch.dm index bdf0001cf17..61df62cf143 100644 --- a/modular_skyrat/modules/aesthetics/lightswitch/code/lightswitch.dm +++ b/modular_skyrat/modules/aesthetics/lightswitch/code/lightswitch.dm @@ -6,7 +6,7 @@ playsound(src, 'modular_skyrat/modules/aesthetics/lightswitch/sound/lightswitch.ogg', 100, 1) #ifndef UNIT_TESTS -/obj/machinery/light_switch/LateInitialize() +/obj/machinery/light_switch/post_machine_initialize() . = ..() if(prob(50) && area.lightswitch) //50% chance for area to start with lights off. turn_off() diff --git a/modular_skyrat/modules/aesthetics/rack/code/rack.dm b/modular_skyrat/modules/aesthetics/rack/code/rack.dm index 23b0beaba07..082e01bb40c 100644 --- a/modular_skyrat/modules/aesthetics/rack/code/rack.dm +++ b/modular_skyrat/modules/aesthetics/rack/code/rack.dm @@ -41,7 +41,7 @@ /obj/structure/rack/gunrack/attackby(obj/item/W, mob/living/user, params) var/list/modifiers = params2list(params) - if (W.tool_behaviour == TOOL_WRENCH && !(obj_flags & NO_DECONSTRUCTION) && LAZYACCESS(modifiers, RIGHT_CLICK)) + if (W.tool_behaviour == TOOL_WRENCH && LAZYACCESS(modifiers, RIGHT_CLICK)) W.play_tool_sound(src) deconstruct(TRUE) return diff --git a/modular_skyrat/modules/aesthetics/status_display/code/status_display.dm b/modular_skyrat/modules/aesthetics/status_display/code/status_display.dm index 1258addd90f..1d34585dad9 100644 --- a/modular_skyrat/modules/aesthetics/status_display/code/status_display.dm +++ b/modular_skyrat/modules/aesthetics/status_display/code/status_display.dm @@ -1,13 +1,13 @@ /obj/machinery/status_display icon = 'modular_skyrat/modules/aesthetics/status_display/icons/status_display.dmi' -/obj/machinery/status_display/LateInitialize() +/obj/machinery/status_display/post_machine_initialize() . = ..() set_picture("default") /obj/machinery/status_display/syndie name = "syndicate status display" -/obj/machinery/status_display/syndie/LateInitialize() +/obj/machinery/status_display/syndie/post_machine_initialize() . = ..() set_picture("synd") diff --git a/modular_skyrat/modules/aesthetics/storage/storage.dmi b/modular_skyrat/modules/aesthetics/storage/storage.dmi index febe4b01547..8a7e15587e6 100644 Binary files a/modular_skyrat/modules/aesthetics/storage/storage.dmi and b/modular_skyrat/modules/aesthetics/storage/storage.dmi differ diff --git a/modular_skyrat/modules/alternative_job_titles/code/alt_job_titles.dm b/modular_skyrat/modules/alternative_job_titles/code/alt_job_titles.dm index 5917558c519..c6ae2743a91 100644 --- a/modular_skyrat/modules/alternative_job_titles/code/alt_job_titles.dm +++ b/modular_skyrat/modules/alternative_job_titles/code/alt_job_titles.dm @@ -139,6 +139,7 @@ "Pontifex", "Rabbi", "Reverend", + "Cleric", ) /datum/job/chemist diff --git a/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm b/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm index ad93830a0b3..64e199150f2 100644 --- a/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm +++ b/modular_skyrat/modules/ammo_workbench/code/ammo_workbench.dm @@ -385,12 +385,12 @@ error_type = "good" return - updateDialog() + SStgui.update_uis(src) timer_id = addtimer(CALLBACK(src, PROC_REF(fill_round), casing_type), time_per_round, TIMER_STOPPABLE) /obj/machinery/ammo_workbench/proc/ammo_fill_finish(successfully = TRUE) - updateDialog() + SStgui.update_uis(src) if(successfully) playsound(loc, 'sound/machines/ping.ogg', 40, TRUE) else diff --git a/modular_skyrat/modules/apc_arcing/code/apc.dm b/modular_skyrat/modules/apc_arcing/code/apc.dm index 9e74d86d157..60413cceae4 100644 --- a/modular_skyrat/modules/apc_arcing/code/apc.dm +++ b/modular_skyrat/modules/apc_arcing/code/apc.dm @@ -35,19 +35,22 @@ playsound(get_turf(living_target), 'sound/magic/lightningshock.ogg', 75, TRUE) Beam(living_target, icon_state = "lightning[rand(1, 12)]", icon = 'icons/effects/beam.dmi', time = 5) -/obj/machinery/power/apc/attackby(obj/item/attacking_object, mob/living/user, params) +/obj/machinery/power/apc/item_interaction(mob/living/user, obj/item/tool, list/modifiers) . = ..() - if(istype(attacking_object, /obj/item/stack/sheet/bronze) && panel_open) - if(arc_shielded) - balloon_alert(user, "already arc shielded!") - return - var/obj/item/stack/sheet/bronze/bronze = attacking_object - bronze.use(1) - balloon_alert(user, "installed arc shielding") - arc_shielded = TRUE - playsound(src, 'sound/items/rped.ogg', 20) - return - + if(.) + return . + if(istype(tool, /obj/item/stack/sheet/bronze) && panel_open) + . = bronze_act(user, tool) +/// Handles interaction of adding arc shielding to apc with bronze +/obj/machinery/power/apc/proc/bronze_act(mob/living/user, obj/item/stack/sheet/bronze/bronze) + if(arc_shielded) + balloon_alert(user, "already arc shielded!") + return ITEM_INTERACT_BLOCKING + bronze.use(1) + balloon_alert(user, "installed arc shielding") + arc_shielded = TRUE + playsound(src, 'sound/items/rped.ogg', 20) + return ITEM_INTERACT_SUCCESS /obj/machinery/power/apc/wrench_act(mob/living/user, obj/item/tool) . = ..() if(panel_open && arc_shielded) diff --git a/modular_skyrat/modules/ashwalkers/code/buildings/fuelwell.dm b/modular_skyrat/modules/ashwalkers/code/buildings/fuelwell.dm index 862d311e16e..be8756b1cf6 100644 --- a/modular_skyrat/modules/ashwalkers/code/buildings/fuelwell.dm +++ b/modular_skyrat/modules/ashwalkers/code/buildings/fuelwell.dm @@ -21,7 +21,7 @@ /obj/structure/sink/fuel_well/attackby(obj/item/O, mob/living/user, params) flick("puddle-oil-splash",src) - if(O.tool_behaviour == TOOL_SHOVEL && !(obj_flags & NO_DECONSTRUCTION)) //attempt to deconstruct the puddle with a shovel + if(O.tool_behaviour == TOOL_SHOVEL) //attempt to deconstruct the puddle with a shovel //attempt to deconstruct the puddle with a shovel to_chat(user, "You fill in the fuel well with soil.") O.play_tool_sound(src) deconstruct() diff --git a/modular_skyrat/modules/ashwalkers/code/buildings/railroad.dm b/modular_skyrat/modules/ashwalkers/code/buildings/railroad.dm index f75ea5248e2..b0b821d7668 100644 --- a/modular_skyrat/modules/ashwalkers/code/buildings/railroad.dm +++ b/modular_skyrat/modules/ashwalkers/code/buildings/railroad.dm @@ -102,9 +102,9 @@ return relaydrive(user, direction) return FALSE -/obj/vehicle/ridden/rail_cart/AltClick(mob/user) - . = ..() +/obj/vehicle/ridden/rail_cart/click_alt(mob/user) attach_trailer() + return CLICK_ACTION_SUCCESS /obj/vehicle/ridden/rail_cart/attack_hand(mob/living/user, list/modifiers) . = ..() diff --git a/modular_skyrat/modules/assault_operatives/code/interrogator.dm b/modular_skyrat/modules/assault_operatives/code/interrogator.dm index 94811938186..6c61caaf498 100644 --- a/modular_skyrat/modules/assault_operatives/code/interrogator.dm +++ b/modular_skyrat/modules/assault_operatives/code/interrogator.dm @@ -36,7 +36,7 @@ . = ..() . += "It requies a direct link to a Nanotrasen defence network, stay near a Nanotrasen comms sat!" -/obj/machinery/interrogator/AltClick(mob/user) +/obj/machinery/interrogator/click_alt(mob/user) . = ..() if(!can_interact(user)) return diff --git a/modular_skyrat/modules/automapper/code/area_spawn_subsystem.dm b/modular_skyrat/modules/automapper/code/area_spawn_subsystem.dm index f0e8af0cdba..ccc2cbbb132 100644 --- a/modular_skyrat/modules/automapper/code/area_spawn_subsystem.dm +++ b/modular_skyrat/modules/automapper/code/area_spawn_subsystem.dm @@ -358,11 +358,7 @@ SUBSYSTEM_DEF(area_spawn) /** * Show overlay over area of priorities. Wall priority over open priority. */ -/client/proc/test_area_spawner(area/area) - set category = "Debug" - set name = "Test Area Spawner" - set desc = "Show area spawner placement candidates as an overlay." - +ADMIN_VERB(test_area_spawner, R_DEBUG, "Test Area Spawner", "Show area spawner placement candidates as an overlay.", ADMIN_CATEGORY_DEBUG, area/area) for(var/obj/effect/turf_test/old_test in area) qdel(old_test) diff --git a/modular_skyrat/modules/awaymissions_skyrat/mothership_astrum/fluff.dm b/modular_skyrat/modules/awaymissions_skyrat/mothership_astrum/fluff.dm index 7fb36157062..78616bbbf62 100644 --- a/modular_skyrat/modules/awaymissions_skyrat/mothership_astrum/fluff.dm +++ b/modular_skyrat/modules/awaymissions_skyrat/mothership_astrum/fluff.dm @@ -5,8 +5,8 @@ icon_state = "alienpaper_words" show_written_words = FALSE -/obj/item/paper/fluff/awaymissions/astrum/AltClick() - return //no folding these +/obj/item/paper/fluff/awaymissions/astrum/click_alt(mob/user) + return NONE //no folding these /obj/item/paper/fluff/awaymissions/astrum/combat name = "Report: Combat Holodeck" diff --git a/modular_skyrat/modules/barricades/code/barricade.dm b/modular_skyrat/modules/barricades/code/barricade.dm index fca6f627624..a3faa5ebef9 100644 --- a/modular_skyrat/modules/barricades/code/barricade.dm +++ b/modular_skyrat/modules/barricades/code/barricade.dm @@ -361,34 +361,34 @@ fire = 80 acid = 40 -/obj/structure/deployable_barricade/metal/AltClick(mob/user) +/obj/structure/deployable_barricade/metal/click_alt(mob/user) if(portable_type) if(anchored) to_chat(user, span_warning("[src] cannot be folded up while anchored to the ground!")) - return FALSE + return CLICK_ACTION_BLOCKING if(barricade_upgrade_type) to_chat(user, span_warning("[src] cannot be folded up with upgrades attached, remove them first!")) - return FALSE + return CLICK_ACTION_BLOCKING if(get_integrity() < max_integrity) to_chat(user, span_warning("[src] cannot be folded up while damaged!")) - return FALSE + return CLICK_ACTION_BLOCKING user.visible_message(span_notice("[user] starts folding [src] up!"), span_notice("You start folding [src] up!")) if(do_after(user, 5 SECONDS, src)) if(QDELETED(src)) //Copied encase we change states. return if(anchored) to_chat(user, span_warning("[src] cannot be folded up while anchored to the ground!")) - return FALSE + return CLICK_ACTION_BLOCKING if(barricade_upgrade_type) to_chat(user, span_warning("[src] cannot be folded up with upgrades attached, remove them first!")) - return FALSE + return CLICK_ACTION_BLOCKING if(get_integrity() < max_integrity) to_chat(user, span_warning("[src] cannot be folded up while damaged!")) - return FALSE + return CLICK_ACTION_BLOCKING user.visible_message(span_notice("[user] folds [src] up!"), span_notice("You neatly fold [src] up!")) playsound(src, 'sound/items/ratchet.ogg', 25, TRUE) fold_up() - return TRUE + return CLICK_ACTION_SUCCESS return ..() /obj/structure/deployable_barricade/metal/proc/fold_up() diff --git a/modular_skyrat/modules/borg_buffs/code/snack_dispensor.dm b/modular_skyrat/modules/borg_buffs/code/snack_dispensor.dm index fe34135c88d..58deaca1d8a 100644 --- a/modular_skyrat/modules/borg_buffs/code/snack_dispensor.dm +++ b/modular_skyrat/modules/borg_buffs/code/snack_dispensor.dm @@ -111,9 +111,10 @@ to_chat(patron, span_notice("[user] dispenses [snack] into your empty hand and you reflexively grasp it.")) to_chat(user, span_notice("You dispense [snack] into the hand of [user].")) -/obj/item/borg_snack_dispenser/AltClick(mob/user) +/obj/item/borg_snack_dispenser/click_alt(mob/user) launch_mode = !launch_mode to_chat(user, span_notice("[src] is [(launch_mode ? "now" : "no longer")] launching snacks at a distance.")) + return CLICK_ACTION_SUCCESS /obj/item/borg_snack_dispenser/afterattack(atom/target, mob/living/silicon/robot/user, proximity_flag, click_parameters) if(Adjacent(target) || !launch_mode) diff --git a/modular_skyrat/modules/borgs/code/robot_items.dm b/modular_skyrat/modules/borgs/code/robot_items.dm index 638fc046676..b5ead250f31 100644 --- a/modular_skyrat/modules/borgs/code/robot_items.dm +++ b/modular_skyrat/modules/borgs/code/robot_items.dm @@ -32,20 +32,20 @@ /obj/item/clipboard/cyborg/examine() . = ..() - . += "Alt-click to synthetize a piece of paper." + . += "Alt-click to synthesize a piece of paper." if(!COOLDOWN_FINISHED(src, printer_cooldown)) - . += "Its integrated paper synthetizer seems to still be on cooldown." + . += "Its integrated paper synthesizer seems to still be on cooldown." -/obj/item/clipboard/cyborg/AltClick(mob/user) +/obj/item/clipboard/cyborg/click_alt(mob/user) if(!iscyborg(user)) to_chat(user, span_warning("You do not seem to understand how to use [src].")) - return + return CLICK_ACTION_BLOCKING var/mob/living/silicon/robot/cyborg_user = user // Not enough charge? Tough luck. if(cyborg_user?.cell.charge < paper_charge_cost) to_chat(user, span_warning("Your internal cell doesn't have enough charge left to use [src]'s integrated printer.")) - return + return CLICK_ACTION_BLOCKING // Check for cooldown to avoid paper spamming if(COOLDOWN_FINISHED(src, printer_cooldown)) // If there's not too much paper already, let's go @@ -61,10 +61,12 @@ toppaper_ref = WEAKREF(new_paper) update_appearance() to_chat(user, span_notice("[src]'s integrated printer whirs to life, spitting out a fresh piece of paper and clipping it into place.")) + return CLICK_ACTION_SUCCESS else to_chat(user, span_warning("[src]'s integrated printer refuses to print more paper, as [src] already contains enough paper.")) else - to_chat(user, span_warning("[src]'s integrated printer refuses to print more paper, its bluespace paper synthetizer not having finished recovering from its last synthesis.")) + to_chat(user, span_warning("[src]'s integrated printer refuses to print more paper, its bluespace paper synthesizer not having finished recovering from its last synthesis.")) + return CLICK_ACTION_BLOCKING /obj/item/hand_labeler/cyborg diff --git a/modular_skyrat/modules/bsa_overhaul/code/admin_verb.dm b/modular_skyrat/modules/bsa_overhaul/code/admin_verb.dm index aa0082ad244..f0d731c4579 100644 --- a/modular_skyrat/modules/bsa_overhaul/code/admin_verb.dm +++ b/modular_skyrat/modules/bsa_overhaul/code/admin_verb.dm @@ -1,10 +1,6 @@ -/client/proc/toggle_bsa() - set category = "Admin.Fun" - set name = "Toggle BSA Control" - set desc = "Toggles the BSA control lock on and off." - +ADMIN_VERB(toggle_bsa, R_ADMIN, "Toggle BSA Control", "Toggles the BSA control lock on and off.", ADMIN_CATEGORY_FUN) GLOB.bsa_unlock = !GLOB.bsa_unlock minor_announce("Bluespace Artillery firing protocols have been [GLOB.bsa_unlock? "unlocked" : "locked"]", "Weapons Systems Update:") message_admins("[ADMIN_LOOKUPFLW(usr)] [GLOB.bsa_unlock? "unlocked" : "locked"] BSA firing protocols.") - log_admin("[key_name(usr)] [GLOB.bsa_unlock? "unlocked" : "locked"] BSA firing protocols.") + log_admin("[key_name(user)] [GLOB.bsa_unlock? "unlocked" : "locked"] BSA firing protocols.") diff --git a/modular_skyrat/modules/bsrpd/code/bsrpd.dm b/modular_skyrat/modules/bsrpd/code/bsrpd.dm index d7493ee1f46..23daac59efa 100644 --- a/modular_skyrat/modules/bsrpd/code/bsrpd.dm +++ b/modular_skyrat/modules/bsrpd/code/bsrpd.dm @@ -48,13 +48,11 @@ . += span_notice("Alt-Click to toggle remote piping.") -/obj/item/pipe_dispenser/bluespace/AltClick(mob/user) - . = ..() - if(. == FALSE) - return // too far away +/obj/item/pipe_dispenser/bluespace/click_alt(mob/user) remote_piping_toggle = !remote_piping_toggle balloon_alert(user, "remote piping [remote_piping_toggle ? "on" : "off"]") playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE) + return CLICK_ACTION_SUCCESS /obj/item/pipe_dispenser/bluespace/afterattack(atom/target, mob/user, prox) if(prox || !remote_piping_toggle) // If we are in proximity to the target or have our safety on, don't use charge and don't call this shitcode. diff --git a/modular_skyrat/modules/cargo_teleporter/code/cargo_teleporter.dm b/modular_skyrat/modules/cargo_teleporter/code/cargo_teleporter.dm index c5e0916f5e9..2efccbe8174 100644 --- a/modular_skyrat/modules/cargo_teleporter/code/cargo_teleporter.dm +++ b/modular_skyrat/modules/cargo_teleporter/code/cargo_teleporter.dm @@ -32,10 +32,11 @@ GLOBAL_LIST_EMPTY(cargo_marks) spawned_marker.parent_item = src marker_children += spawned_marker -/obj/item/cargo_teleporter/AltClick(mob/user) +/obj/item/cargo_teleporter/click_alt(mob/user) if(length(marker_children)) for(var/obj/effect/decal/cleanable/cargo_mark/destroy_children in marker_children) qdel(destroy_children) + return CLICK_ACTION_SUCCESS /obj/item/cargo_teleporter/afterattack(atom/target, mob/user, proximity_flag, click_parameters) if(!proximity_flag) diff --git a/modular_skyrat/modules/cellguns/code/cellguns.dm b/modular_skyrat/modules/cellguns/code/cellguns.dm index eaeaee29cc2..cce7b4435ef 100644 --- a/modular_skyrat/modules/cellguns/code/cellguns.dm +++ b/modular_skyrat/modules/cellguns/code/cellguns.dm @@ -72,10 +72,10 @@ charge_overlay.pixel_y = ammo_y_offset * (i - 1) . += new /mutable_appearance(charge_overlay) -/obj/item/gun/energy/cell_loaded/AltClick(mob/user, modifiers) +/obj/item/gun/energy/cell_loaded/click_alt(mob/user, modifiers) if(!installedcells.len) //Checks to see if there is a cell inside of the gun, before removal. to_chat(user, span_notice("The [src] has no cells inside")) - return ..() + return CLICK_ACTION_BLOCKING to_chat(user, span_notice("You remove a cell")) var/obj/item/last_cell = installedcells[installedcells.len] @@ -87,6 +87,7 @@ installedcells -= last_cell ammo_type.len-- select_fire(user) + return CLICK_ACTION_SUCCESS /// A cellgun used for debug, it is able to use any weaponcell. /obj/item/gun/energy/cell_loaded/alltypes diff --git a/modular_skyrat/modules/cellguns/code/medigun_cells.dm b/modular_skyrat/modules/cellguns/code/medigun_cells.dm index 274a523a7d4..4c58e129fb7 100644 --- a/modular_skyrat/modules/cellguns/code/medigun_cells.dm +++ b/modular_skyrat/modules/cellguns/code/medigun_cells.dm @@ -538,7 +538,6 @@ icon_state = "hardlight_down" base_icon_state = "hardlight" max_integrity = 1 - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION //Made from nothing, can't deconstruct build_stack_type = null //It would not be good if people could use this to farm materials. var/deploy_time = 20 SECONDS //How long the roller beds lasts for without someone buckled to it. @@ -546,6 +545,10 @@ . = ..() addtimer(CALLBACK(src, PROC_REF(check_bed)), deploy_time) +// previously NO_DECONSTRUCTION +/obj/structure/bed/medical/medigun/wrench_act_secondary(mob/living/user, obj/item/weapon) + return NONE + /obj/structure/bed/medical/medigun/proc/check_bed() //Checks to see if anyone is buckled to the bed, if not the bed will qdel itself. if(!has_buckled_mobs()) qdel(src) //Deletes the roller bed, mostly meant to prevent stockpiling and clutter diff --git a/modular_skyrat/modules/cellguns/code/mediguns.dm b/modular_skyrat/modules/cellguns/code/mediguns.dm index 3a79fce401b..deb6e02b0c4 100644 --- a/modular_skyrat/modules/cellguns/code/mediguns.dm +++ b/modular_skyrat/modules/cellguns/code/mediguns.dm @@ -49,18 +49,18 @@ // Medigun power cells /obj/item/stock_parts/cell/medigun // This is the cell that mediguns from cargo will come with name = "basic medigun cell" - maxcharge = 1200 - chargerate = 40 + maxcharge = STANDARD_CELL_CHARGE + chargerate = STANDARD_CELL_CHARGE * 0.03 /obj/item/stock_parts/cell/medigun/upgraded name = "upgraded medigun cell" - maxcharge = 1500 - chargerate = 80 + maxcharge = STANDARD_CELL_CHARGE * 1.4 + chargerate = STANDARD_CELL_CHARGE * 0.06 /obj/item/stock_parts/cell/medigun/experimental // This cell type is meant to be used in self charging mediguns like CMO and ERT one. name = "experiemental medigun cell" - maxcharge = 1800 - chargerate = 100 + maxcharge = STANDARD_CELL_CHARGE * 2 + chargerate = STANDARD_CELL_CHARGE * 0.1 // End of power cells // Upgrade Kit diff --git a/modular_skyrat/modules/central_command_module/code/computers/station_goal_computer.dm b/modular_skyrat/modules/central_command_module/code/computers/station_goal_computer.dm index a1464e08d3e..9b488fd561f 100644 --- a/modular_skyrat/modules/central_command_module/code/computers/station_goal_computer.dm +++ b/modular_skyrat/modules/central_command_module/code/computers/station_goal_computer.dm @@ -47,8 +47,6 @@ if(machine_stat & (NOPOWER|BROKEN|MAINT)) return - usr.set_machine(src) - var/selected_goal = href_list["selected_goal"] if(href_list["close"]) @@ -62,4 +60,4 @@ SSstation.goals_by_type[iterating_goal] = goal_to_set goal_assigned = TRUE break - updateUsrDialog() + SStgui.update_uis(src) diff --git a/modular_skyrat/modules/colony_fabricator/code/appliances/wall_cell_charger.dm b/modular_skyrat/modules/colony_fabricator/code/appliances/wall_cell_charger.dm index 8434a730f1d..e126baca3d0 100644 --- a/modular_skyrat/modules/colony_fabricator/code/appliances/wall_cell_charger.dm +++ b/modular_skyrat/modules/colony_fabricator/code/appliances/wall_cell_charger.dm @@ -5,7 +5,6 @@ icon_state = "wall_charger" base_icon_state = "wall_charger" circuit = null - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION max_batteries = 3 charge_rate = 900 KILO WATTS /// The item we turn into when repacked @@ -27,6 +26,16 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/cell_charger_multi/wall_mounted, 29) deconstruct(TRUE) return +// previously NO_DECONSTRUCTION +/obj/machinery/cell_charger_multi/wall_mounted/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) + return NONE + +/obj/machinery/cell_charger_multi/wall_mounted/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct) + return NONE + +/obj/machinery/cell_charger_multi/wall_mounted/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density) + return NONE + /obj/machinery/cell_charger_multi/wall_mounted/on_deconstruction(disassembled) if(disassembled) new repacked_type(drop_location()) diff --git a/modular_skyrat/modules/colony_fabricator/code/colony_fabricator.dm b/modular_skyrat/modules/colony_fabricator/code/colony_fabricator.dm index f7d7eede0ac..1eb2a4627e1 100644 --- a/modular_skyrat/modules/colony_fabricator/code/colony_fabricator.dm +++ b/modular_skyrat/modules/colony_fabricator/code/colony_fabricator.dm @@ -9,7 +9,6 @@ production_animation = null circuit = null production_animation = "colony_lathe_n" - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION light_color = LIGHT_COLOR_BRIGHT_YELLOW light_power = 5 allowed_buildtypes = COLONY_FABRICATOR @@ -33,6 +32,16 @@ QDEL_NULL(soundloop) return ..() +// previously NO_DECONSTRUCTION +/obj/machinery/rnd/production/colony_lathe/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) + return NONE + +/obj/machinery/rnd/production/colony_lathe/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct) + return NONE + +/obj/machinery/rnd/production/colony_lathe/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density) + return NONE + /obj/machinery/rnd/production/colony_lathe/ui_act(action, list/params, datum/tgui/ui) . = ..() if (. && action == "build") diff --git a/modular_skyrat/modules/colony_fabricator/code/design_datums/appliances.dm b/modular_skyrat/modules/colony_fabricator/code/design_datums/appliances.dm index a7efee044b8..c600019f7de 100644 --- a/modular_skyrat/modules/colony_fabricator/code/design_datums/appliances.dm +++ b/modular_skyrat/modules/colony_fabricator/code/design_datums/appliances.dm @@ -18,7 +18,6 @@ "portable_lil_pump", "portable_scrubbs", "survival_knife", // I just don't want to make a whole new node for this one sorry - "soup_pot", // This one too "water_synth", "hydro_synth", "frontier_sustenance_dispenser", diff --git a/modular_skyrat/modules/colony_fabricator/code/design_datums/equipment.dm b/modular_skyrat/modules/colony_fabricator/code/design_datums/equipment.dm index 067b0084046..d2c0f8887f2 100644 --- a/modular_skyrat/modules/colony_fabricator/code/design_datums/equipment.dm +++ b/modular_skyrat/modules/colony_fabricator/code/design_datums/equipment.dm @@ -12,16 +12,8 @@ ) departmental_flags = DEPARTMENT_BITFLAG_SERVICE -/datum/design/soup_pot - name = "Soup Pot" - id = "soup_pot" - build_type = COLONY_FABRICATOR - materials = list( - /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5, - ) - build_path = /obj/item/reagent_containers/cup/soup_pot - category = list( - RND_CATEGORY_INITIAL, - RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_KITCHEN, - ) - departmental_flags = DEPARTMENT_BITFLAG_SERVICE +// Lets colony fabricators make soup pots, removes bluespace crystal requirement. +/datum/design/soup_pot/New() + build_type |= COLONY_FABRICATOR + materials -= /datum/material/bluespace + return ..() diff --git a/modular_skyrat/modules/colony_fabricator/code/machines/arc_furnace.dm b/modular_skyrat/modules/colony_fabricator/code/machines/arc_furnace.dm index acf3d2af90f..6d692728674 100644 --- a/modular_skyrat/modules/colony_fabricator/code/machines/arc_furnace.dm +++ b/modular_skyrat/modules/colony_fabricator/code/machines/arc_furnace.dm @@ -18,7 +18,6 @@ circuit = null light_color = LIGHT_COLOR_BRIGHT_YELLOW light_power = 10 - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 10 // This baby consumes so much power /// The item we turn into when repacked var/repacked_type = /obj/item/flatpacked_machine/arc_furnace @@ -46,6 +45,16 @@ if(length(contents)) . += span_notice("It has [contents[1]] sitting in it.") +// previously NO_DECONSTRUCTION +/obj/machinery/arc_furnace/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) + return NONE + +/obj/machinery/arc_furnace/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct) + return NONE + +/obj/machinery/arc_furnace/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density) + return NONE + /obj/machinery/arc_furnace/on_deconstruction(disassembled) eject_contents() @@ -98,7 +107,6 @@ if(isAI(user) && (machine_stat & NOPOWER)) return - usr.set_machine(src) // What does this even do?? switch(choice) if(RADIAL_CHOICE_EJECT) eject_contents() diff --git a/modular_skyrat/modules/colony_fabricator/code/machines/power_storage_unit.dm b/modular_skyrat/modules/colony_fabricator/code/machines/power_storage_unit.dm index cd2da64f8e4..4d6fc605a79 100644 --- a/modular_skyrat/modules/colony_fabricator/code/machines/power_storage_unit.dm +++ b/modular_skyrat/modules/colony_fabricator/code/machines/power_storage_unit.dm @@ -9,7 +9,6 @@ input_level_max = 400 * 1000 output_level_max = 400 * 1000 circuit = null - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION /// The item we turn into when repacked var/repacked_type = /obj/item/flatpacked_machine/station_battery @@ -34,6 +33,13 @@ to_chat(user, span_notice("You close the maintenance hatch of [src].")) return TRUE +// previously NO_DECONSTRUCTION +/obj/machinery/power/smes/battery_pack/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct) + return NONE + +/obj/machinery/power/smes/battery_pack/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density) + return NONE + // We don't care about the parts updates because we don't want them to change /obj/machinery/power/smes/battery_pack/RefreshParts() return diff --git a/modular_skyrat/modules/colony_fabricator/code/machines/rtg.dm b/modular_skyrat/modules/colony_fabricator/code/machines/rtg.dm index c01724200ac..5690e26884a 100644 --- a/modular_skyrat/modules/colony_fabricator/code/machines/rtg.dm +++ b/modular_skyrat/modules/colony_fabricator/code/machines/rtg.dm @@ -6,7 +6,6 @@ application." icon = 'modular_skyrat/modules/colony_fabricator/icons/machines.dmi' circuit = null - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION power_gen = 7500 /// What we turn into when we are repacked var/repacked_type = /obj/item/flatpacked_machine/rtg @@ -19,8 +18,17 @@ if(!mapload) flick("rtg_deploy", src) -// Item for creating the arc furnace or carrying it around +// previously NO_DECONSTRUCTION +/obj/machinery/power/rtg/portable/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) + return NONE +/obj/machinery/power/rtg/portable/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct) + return NONE + +/obj/machinery/power/rtg/portable/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density) + return NONE + +// Item for creating the arc furnace or carrying it around /obj/item/flatpacked_machine/rtg name = "flat-packed radioisotope thermoelectric generator" icon_state = "rtg_packed" diff --git a/modular_skyrat/modules/colony_fabricator/code/machines/solar_panels.dm b/modular_skyrat/modules/colony_fabricator/code/machines/solar_panels.dm index c965d5ab169..9b8f02db090 100644 --- a/modular_skyrat/modules/colony_fabricator/code/machines/solar_panels.dm +++ b/modular_skyrat/modules/colony_fabricator/code/machines/solar_panels.dm @@ -2,7 +2,6 @@ /obj/machinery/power/solar/deployable icon = 'modular_skyrat/modules/colony_fabricator/icons/machines.dmi' - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION /// The item we turn into when repacked var/repacked_type = /obj/item/flatpacked_machine/solar @@ -20,6 +19,16 @@ qdel(assembly) return ..() +// previously NO_DECONSTRUCTION +/obj/machinery/power/solar/deployable/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) + return NONE + +/obj/machinery/power/solar/deployable/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct) + return NONE + +/obj/machinery/power/solar/deployable/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density) + return NONE + // Solar panel deployable item /obj/item/flatpacked_machine/solar @@ -37,7 +46,6 @@ /obj/machinery/power/tracker/deployable icon = 'modular_skyrat/modules/colony_fabricator/icons/machines.dmi' - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION /// The item we turn into when repacked var/repacked_type = /obj/item/flatpacked_machine/solar_tracker @@ -47,7 +55,17 @@ AddElement(/datum/element/manufacturer_examine, COMPANY_FRONTIER) /obj/machinery/power/tracker/deployable/crowbar_act(mob/user, obj/item/item_acting) - return + return NONE + +// previously NO_DECONSTRUCTION +/obj/machinery/power/tracker/deployable/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) + return NONE + +/obj/machinery/power/tracker/deployable/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct) + return NONE + +/obj/machinery/power/tracker/deployable/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density) + return NONE /obj/machinery/power/tracker/deployable/on_deconstruction(disassembled) var/obj/item/solar_assembly/assembly = locate() in src diff --git a/modular_skyrat/modules/colony_fabricator/code/machines/solid_fuel_generator.dm b/modular_skyrat/modules/colony_fabricator/code/machines/solid_fuel_generator.dm index a3ac75a0825..e082b8bea0a 100644 --- a/modular_skyrat/modules/colony_fabricator/code/machines/solid_fuel_generator.dm +++ b/modular_skyrat/modules/colony_fabricator/code/machines/solid_fuel_generator.dm @@ -11,7 +11,6 @@ icon_state = "fuel_generator_0" base_icon_state = "fuel_generator" circuit = null - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION anchored = TRUE max_sheets = 25 time_per_sheet = 100 @@ -28,6 +27,16 @@ if(!mapload) flick("fuel_generator_deploy", src) +// previously NO_DECONSTRUCTION +/obj/machinery/power/port_gen/pacman/solid_fuel/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) + return NONE + +/obj/machinery/power/port_gen/pacman/solid_fuel/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct) + return NONE + +/obj/machinery/power/port_gen/pacman/solid_fuel/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density) + return NONE + // We don't need to worry about the board, this machine doesn't have one! /obj/machinery/power/port_gen/pacman/solid_fuel/on_construction(mob/user) return diff --git a/modular_skyrat/modules/conveyor_sorter/code/conveyor_sorter.dm b/modular_skyrat/modules/conveyor_sorter/code/conveyor_sorter.dm index 550de51f205..a5306c96bd2 100644 --- a/modular_skyrat/modules/conveyor_sorter/code/conveyor_sorter.dm +++ b/modular_skyrat/modules/conveyor_sorter/code/conveyor_sorter.dm @@ -53,10 +53,11 @@ current_sort += target.type to_chat(user, span_notice("[target] has been added to [src]'s sorting list.")) -/obj/item/conveyor_sorter/AltClick(mob/user) +/obj/item/conveyor_sorter/click_alt(mob/user) visible_message("[src] pings, resetting its sorting list!") playsound(src, 'sound/machines/ping.ogg', 30, TRUE) current_sort = list() + return CLICK_ACTION_SUCCESS /obj/effect/decal/conveyor_sorter name = "conveyor sorter" @@ -122,10 +123,11 @@ else return ..() -/obj/effect/decal/conveyor_sorter/AltClick(mob/user) +/obj/effect/decal/conveyor_sorter/click_alt(mob/user) visible_message("[src] pings, resetting its sorting list!") playsound(src, 'sound/machines/ping.ogg', 30, TRUE) sorting_list = list() + return CLICK_ACTION_SUCCESS /obj/effect/decal/conveyor_sorter/CtrlClick(mob/user) visible_message("[src] begins to ping violently!") diff --git a/modular_skyrat/modules/cryosleep/code/cryopod.dm b/modular_skyrat/modules/cryosleep/code/cryopod.dm index baf3ec481c0..ea5cc83c3ec 100644 --- a/modular_skyrat/modules/cryosleep/code/cryopod.dm +++ b/modular_skyrat/modules/cryosleep/code/cryopod.dm @@ -179,7 +179,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/cryopod, 32) GLOB.valid_cryopods += src return INITIALIZE_HINT_LATELOAD //Gotta populate the cryopod computer GLOB first -/obj/machinery/cryopod/LateInitialize() +/obj/machinery/cryopod/post_machine_initialize() + . = ..() update_icon() find_control_computer() diff --git a/modular_skyrat/modules/customization/modules/clothing/masks/paper.dm b/modular_skyrat/modules/customization/modules/clothing/masks/paper.dm index e141f569004..b9ff2f16cc8 100644 --- a/modular_skyrat/modules/customization/modules/clothing/masks/paper.dm +++ b/modular_skyrat/modules/customization/modules/clothing/masks/paper.dm @@ -57,7 +57,6 @@ /obj/item/clothing/mask/paper/Initialize(mapload) . = ..() - register_context() if(wear_hair_over) alternate_worn_layer = BACK_LAYER diff --git a/modular_skyrat/modules/customization/modules/clothing/neck/_neck.dm b/modular_skyrat/modules/customization/modules/clothing/neck/_neck.dm index 75c95556f6d..0135ef01d82 100644 --- a/modular_skyrat/modules/customization/modules/clothing/neck/_neck.dm +++ b/modular_skyrat/modules/customization/modules/clothing/neck/_neck.dm @@ -103,12 +103,12 @@ . = ..() AddComponent(/datum/component/toggle_icon, toggle_noun = "scarf") -/obj/item/clothing/neck/face_scarf/AltClick(mob/user) //Make sure that toggling actually hides the snout so that it doesn't clip - . = ..() +/obj/item/clothing/neck/face_scarf/click_alt(mob/user) //Make sure that toggling actually hides the snout so that it doesn't clip if(icon_state != "face_scarf_t") flags_inv = HIDEFACIALHAIR | HIDESNOUT else flags_inv = HIDEFACIALHAIR + return CLICK_ACTION_SUCCESS /obj/item/clothing/neck/maid_neck_cover name = "maid neck cover" diff --git a/modular_skyrat/modules/customization/modules/clothing/storage/belts.dm b/modular_skyrat/modules/customization/modules/clothing/storage/belts.dm index fa4052d1119..322e438374c 100644 --- a/modular_skyrat/modules/customization/modules/clothing/storage/belts.dm +++ b/modular_skyrat/modules/customization/modules/clothing/storage/belts.dm @@ -7,6 +7,7 @@ worn_icon_state = "crusader_belt" inhand_icon_state = "utility" w_class = WEIGHT_CLASS_BULKY //Cant fit a sheath in your bag + interaction_flags_click = NEED_DEXTERITY /obj/item/storage/belt/crusader/Initialize(mapload) . = ..() @@ -64,9 +65,7 @@ atom_storage.show_contents(user) return -/obj/item/storage/belt/crusader/AltClick(mob/user) //This is basically the same as the normal sheath, but because there's always an item locked in the first slot it uses the second slot for swords - if(!user.can_perform_action(src, NEED_DEXTERITY)) - return +/obj/item/storage/belt/crusader/click_alt(mob/user) //This is basically the same as the normal sheath, but because there's always an item locked in the first slot it uses the second slot for swords if(contents.len == 2) var/obj/item/drawn_item = contents[2] add_fingerprint(user) @@ -74,12 +73,12 @@ if(!user.put_in_hands(drawn_item)) to_chat(user, span_notice("You fumble for [drawn_item] and it falls on the floor.")) update_appearance() - return + return CLICK_ACTION_SUCCESS user.visible_message(span_notice("[user] takes [drawn_item] out of [src]."), span_notice("You take [drawn_item] out of [src].")) update_appearance() else to_chat(user, span_warning("[src] is empty!")) - . = ..() + return CLICK_ACTION_SUCCESS /obj/item/storage/belt/crusader/update_icon(updates) if(contents.len == 2) //Checks for a sword/rod in the sheath slot, changes the sprite accordingly 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 8ecb31de46c..51c37671727 100644 --- a/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm +++ b/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm @@ -280,14 +280,14 @@ visor_flags_inv = HIDESNOUT // | HIDEFACE // bubber edit // BUBBER TODO: Modularity w_class = WEIGHT_CLASS_SMALL tint = 0 + interaction_flags_click = NEED_DEXTERITY /obj/item/clothing/mask/gas/nightlight/attack_self(mob/user) adjustmask(user) -/obj/item/clothing/mask/gas/nightlight/AltClick(mob/user) - ..() - if(user.can_perform_action(src, NEED_DEXTERITY)) - adjustmask(user) +/obj/item/clothing/mask/gas/nightlight/click_alt(mob/user) + adjustmask(user) + return CLICK_ACTION_SUCCESS /obj/item/clothing/mask/gas/nightlight/examine(mob/user) . = ..() @@ -798,7 +798,6 @@ worn_icon = 'modular_skyrat/master_files/icons/donator/mob/clothing/head.dmi' icon_state = "emissionhelm" - // Donation reward for CandleJax /obj/item/clothing/head/helmet/space/plasmaman/candlejax2 name = "azulean's environment helmet" diff --git a/modular_skyrat/modules/customization/modules/clothing/~donator/donator_items.dm b/modular_skyrat/modules/customization/modules/clothing/~donator/donator_items.dm index 6455bba4255..4cd4695d2fb 100644 --- a/modular_skyrat/modules/customization/modules/clothing/~donator/donator_items.dm +++ b/modular_skyrat/modules/customization/modules/clothing/~donator/donator_items.dm @@ -256,11 +256,11 @@ else icon_state = "catear_headphone[song?.playing ? "_on" : null]" -/obj/item/instrument/piano_synth/headphones/catear_headphone/AltClick(mob/user) - . = ..() +/obj/item/instrument/piano_synth/headphones/catear_headphone/click_alt(mob/user) catTailToggled = !catTailToggled user.update_worn_head() update_icon(UPDATE_OVERLAYS) + return CLICK_ACTION_SUCCESS /obj/item/instrument/piano_synth/headphones/catear_headphone/update_overlays() . = ..() diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm index 44f5dc23227..98bda575348 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species.dm @@ -137,9 +137,7 @@ GLOBAL_LIST_EMPTY(customizable_races) if(eye_organ) eye_organ.refresh(call_update = FALSE) - for(var/mutable_appearance/eye_overlay in eye_organ.generate_body_overlay(species_human)) - eye_overlay.pixel_y += height_offset - standing += eye_overlay + standing += eye_organ.generate_body_overlay(species_human) //Underwear, Undershirts & Socks if(!HAS_TRAIT(species_human, TRAIT_NO_UNDERWEAR)) diff --git a/modular_skyrat/modules/decay_subsystem/code/spawn_nest.dm b/modular_skyrat/modules/decay_subsystem/code/spawn_nest.dm index 5ab0c9a713b..9227b8582b2 100644 --- a/modular_skyrat/modules/decay_subsystem/code/spawn_nest.dm +++ b/modular_skyrat/modules/decay_subsystem/code/spawn_nest.dm @@ -1,9 +1,5 @@ -/client/proc/spawn_mob_spawner() - set category = "Admin.Fun" - set name = "Spawn mob spawner" - set desc = "Spawns a mob spawner structure below the user." - - holder?.spawn_mob_spawner() +ADMIN_VERB(spawn_mob_spawner, R_ADMIN, "Spawn mob spawner", "Spawns a mob spawner structure at your location.", ADMIN_CATEGORY_FUN) + user.holder?.spawn_mob_spawner() /datum/admins/proc/spawn_mob_spawner(chosen_mob as text) if(!check_rights(R_SPAWN)) diff --git a/modular_skyrat/modules/delam_emergency_stop/code/admin_scram.dm b/modular_skyrat/modules/delam_emergency_stop/code/admin_scram.dm index fc338d7b214..0d4a99627c3 100644 --- a/modular_skyrat/modules/delam_emergency_stop/code/admin_scram.dm +++ b/modular_skyrat/modules/delam_emergency_stop/code/admin_scram.dm @@ -1,12 +1,7 @@ /// Lets an admin activate the delam suppression system -/client/proc/try_stop_delam() - set name = "Delam Emergency Stop" - set category = "Admin.Events" +ADMIN_VERB(try_stop_delam, R_ADMIN, "Delam Emergency Stop", "Activate the delam suppression system.", ADMIN_CATEGORY_EVENTS) var/obj/machinery/atmospherics/components/unary/delam_scram/suppression_system = null - if(!holder || !check_rights(R_FUN)) - return - suppression_system = validate_suppression_status() if(!suppression_system) @@ -14,19 +9,19 @@ // Warn them if they're intervening in the work of God if(world.time - SSticker.round_start_time < 30 MINUTES) - var/go_early = tgui_alert(usr, "The [suppression_system.name] is set to automatically start at the programmed time. \ + var/go_early = tgui_alert(user, "The [suppression_system.name] is set to automatically start at the programmed time. \ Are you sure you want to override this and fire it early? It's less scary that way.", "Suffering premature delamination?", list("No", "Yes")) if(go_early != "Yes") return FALSE - var/double_check = tgui_alert(usr, "You really sure that you want to push this?", "Reticulating Splines", list("No", "Yes")) + var/double_check = tgui_alert(user, "You really sure that you want to push this?", "Reticulating Splines", list("No", "Yes")) if(double_check != "Yes") return FALSE // Send the signal to start, unlock the temp emergency exits - log_admin("[key_name_admin(usr)] started a supermatter emergency stop!") - message_admins("[ADMIN_LOOKUPFLW(usr)] started a supermatter emergency stop! [ADMIN_COORDJMP(suppression_system)]") - suppression_system.investigate_log("[key_name_admin(usr)] started a supermatter emergency stop!", INVESTIGATE_ATMOS) + log_admin("[key_name_admin(user)] started a supermatter emergency stop!") + message_admins("[ADMIN_LOOKUPFLW(user)] started a supermatter emergency stop! [ADMIN_COORDJMP(suppression_system)]") + suppression_system.investigate_log("[key_name_admin(user)] started a supermatter emergency stop!", INVESTIGATE_ATMOS) SEND_GLOBAL_SIGNAL(COMSIG_MAIN_SM_DELAMINATING, DIVINE_INTERVENTION) for(var/obj/machinery/door/airlock/escape_route in range(14, suppression_system)) // a little more space here due to positioning if(istype(escape_route, /obj/machinery/door/airlock/command)) @@ -34,13 +29,10 @@ INVOKE_ASYNC(escape_route, TYPE_PROC_REF(/obj/machinery/door/airlock, temp_emergency_exit), 45 SECONDS) /// Lets admins disable/enable the delam suppression system +ADMIN_VERB(toggle_delam_suppression, R_FUN, "Delam Suppression Toggle", "Disable/enable the delam suppression system.", ADMIN_CATEGORY_EVENTS) + user.mob.client?.toggle_delam_suppression() + /client/proc/toggle_delam_suppression() - set name = "Delam Suppression Toggle" - set category = "Admin.Events" - - if(!holder || !check_rights(R_FUN)) - return - var/obj/machinery/atmospherics/components/unary/delam_scram/suppression_system = validate_suppression_status() if(!suppression_system) diff --git a/modular_skyrat/modules/delam_emergency_stop/code/scram.dm b/modular_skyrat/modules/delam_emergency_stop/code/scram.dm index c83856bfb1c..2d5481b2747 100644 --- a/modular_skyrat/modules/delam_emergency_stop/code/scram.dm +++ b/modular_skyrat/modules/delam_emergency_stop/code/scram.dm @@ -63,7 +63,7 @@ return INITIALIZE_HINT_LATELOAD -/obj/machinery/atmospherics/components/unary/delam_scram/LateInitialize() +/obj/machinery/atmospherics/components/unary/delam_scram/post_machine_initialize() . = ..() if(isnull(id_tag)) id_tag = "SCRAM" @@ -387,7 +387,7 @@ else if(machine_stat & (NOPOWER|BROKEN)) icon_state += "-nopower" -/obj/machinery/power/emitter/LateInitialize(mapload) +/obj/machinery/power/emitter/post_machine_initialize() . = ..() RegisterSignal(SSdcs, COMSIG_MAIN_SM_DELAMINATING, PROC_REF(emergency_stop)) diff --git a/modular_skyrat/modules/electric_welder/code/electric_welder.dm b/modular_skyrat/modules/electric_welder/code/electric_welder.dm index a3426e2cf78..c61e8333ef9 100644 --- a/modular_skyrat/modules/electric_welder/code/electric_welder.dm +++ b/modular_skyrat/modules/electric_welder/code/electric_welder.dm @@ -71,10 +71,6 @@ /obj/item/weldingtool/electric/use(used = 0) return isOn() -// This is what starts fires. Overriding it stops it starting fires -/obj/item/weldingtool/electric/handle_fuel_and_temps(used = 0, mob/living/user) - return - /obj/item/weldingtool/electric/examine() . = ..() . += "[src] is currently [powered ? "powered" : "unpowered"]." diff --git a/modular_skyrat/modules/events/code/event_spawner_menu.dm b/modular_skyrat/modules/events/code/event_spawner_menu.dm index 94be670b8ed..7f839bcfc13 100644 --- a/modular_skyrat/modules/events/code/event_spawner_menu.dm +++ b/modular_skyrat/modules/events/code/event_spawner_menu.dm @@ -366,13 +366,7 @@ ShowPanel(usr, null) return -/client/proc/admin_open_event_spawners_menu() - set category = "Admin.Events" - set name = "Event Spawners Menu" - - if(!check_rights(R_ADMIN)) - return - +ADMIN_VERB(admin_open_event_spawners_menu, R_ADMIN, "Event Spawners Menu", "Event Spawners Menu.", ADMIN_CATEGORY_EVENTS) var/datum/event_spawner_manager/ESM = GLOB.event_spawner_manager ESM.ShowPanel(usr, null) diff --git a/modular_skyrat/modules/exp_corps/code/clothing.dm b/modular_skyrat/modules/exp_corps/code/clothing.dm index 66e5422f012..d932d13b3ad 100644 --- a/modular_skyrat/modules/exp_corps/code/clothing.dm +++ b/modular_skyrat/modules/exp_corps/code/clothing.dm @@ -240,12 +240,9 @@ current_user.remove_client_colour(/datum/client_colour/glass_colour/lightgreen) current_user.update_sight() -/obj/item/clothing/head/helmet/expeditionary_corps/AltClick(mob/user) - . = ..() +/obj/item/clothing/head/helmet/expeditionary_corps/click_alt(mob/user) if(!current_user) return - if(!can_interact(user)) - return nightvision = !nightvision if(nightvision) @@ -255,6 +252,7 @@ to_chat(user, span_notice("You flip the NV goggles up.")) disable_nv() update_appearance() + return CLICK_ACTION_SUCCESS /obj/item/clothing/head/helmet/expeditionary_corps/dropped(mob/user) . = ..() diff --git a/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm b/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm index 5d2f0d34e72..70ae903aa63 100644 --- a/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm +++ b/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm @@ -392,11 +392,11 @@ ), ) -/obj/item/clothing/neck/security_cape/AltClick(mob/user) - . = ..() +/obj/item/clothing/neck/security_cape/click_alt(mob/user) swapped = !swapped to_chat(user, span_notice("You swap which arm [src] will lay over.")) update_appearance() + return CLICK_ACTION_SUCCESS /obj/item/clothing/neck/security_cape/update_appearance(updates) . = ..() diff --git a/modular_skyrat/modules/hev_suit/code/hev_suit.dm b/modular_skyrat/modules/hev_suit/code/hev_suit.dm index 1dbce983d32..eff170f0c7a 100644 --- a/modular_skyrat/modules/hev_suit/code/hev_suit.dm +++ b/modular_skyrat/modules/hev_suit/code/hev_suit.dm @@ -843,9 +843,11 @@ acid_static_cooldown = PCV_COOLDOWN_ACID suit_name = "PCV MARK II" -/obj/item/clothing/suit/space/hev_suit/pcv/AltClick(mob/living/user) - reskin_obj(user) +/obj/item/clothing/suit/space/hev_suit/pcv/add_context(atom/source, list/context, obj/item/held_item, mob/user) . = ..() + if(!current_skin) + context[SCREENTIP_CONTEXT_ALT_LMB] = "Reskin" + return CONTEXTUAL_SCREENTIP_SET #undef HEV_COLOR_GREEN #undef HEV_COLOR_RED diff --git a/modular_skyrat/modules/ices_events/code/ICES_tgui.dm b/modular_skyrat/modules/ices_events/code/ICES_tgui.dm index fb4c04a3678..6d28556209d 100644 --- a/modular_skyrat/modules/ices_events/code/ICES_tgui.dm +++ b/modular_skyrat/modules/ices_events/code/ICES_tgui.dm @@ -1,12 +1,6 @@ ///Allows an admin to open the panel -/client/proc/intensity_credits_panel() - set name = "ICES Events Panel" - set category = "Admin.Events" - - if(!holder || !check_rights(R_FUN)) - return - - holder.intensity_credits_panel() +ADMIN_VERB(intensity_credits_panel, R_FUN, "ICES Events Panel", "Opens up the ICES panel.", ADMIN_CATEGORY_EVENTS) + user.holder?.intensity_credits_panel() ///Opens up the ICES panel /datum/admins/proc/intensity_credits_panel() diff --git a/modular_skyrat/modules/inflatables/code/inflatable.dm b/modular_skyrat/modules/inflatables/code/inflatable.dm index f58b4dde172..47cfef36777 100644 --- a/modular_skyrat/modules/inflatables/code/inflatable.dm +++ b/modular_skyrat/modules/inflatables/code/inflatable.dm @@ -53,11 +53,9 @@ return return ..() -/obj/structure/inflatable/AltClick(mob/user) - . = ..() - if(!user.can_interact_with(src)) - return +/obj/structure/inflatable/click_alt(mob/user) deflate(FALSE) + return CLICK_ACTION_SUCCESS /obj/structure/inflatable/play_attack_sound(damage_amount, damage_type, damage_flag) playsound(src, hit_sound, 75, TRUE) diff --git a/modular_skyrat/modules/interaction_menu/code/interaction_datum.dm b/modular_skyrat/modules/interaction_menu/code/interaction_datum.dm index 6f83d6b41b8..d28aec8e8b0 100644 --- a/modular_skyrat/modules/interaction_menu/code/interaction_datum.dm +++ b/modular_skyrat/modules/interaction_menu/code/interaction_datum.dm @@ -261,11 +261,5 @@ GLOBAL_LIST_EMPTY_TYPED(interaction_instances, /datum/interaction) GLOB.interaction_instances[iname] = interaction -/client/proc/reload_interactions() - set category = "Debug" - set name = "Reload Interactions" - set desc = "Force reload interactions" - if(!check_rights(R_DEBUG)) - return - +ADMIN_VERB(reload_interactions, R_DEBUG, "Reload Interactions", "Force reload interactions.", ADMIN_CATEGORY_DEBUG) populate_interaction_instances() diff --git a/modular_skyrat/modules/jukebox/code/dance_machine.dm b/modular_skyrat/modules/jukebox/code/dance_machine.dm index 09d335f4460..54c8e27ed89 100644 --- a/modular_skyrat/modules/jukebox/code/dance_machine.dm +++ b/modular_skyrat/modules/jukebox/code/dance_machine.dm @@ -37,8 +37,6 @@ desc = "Now redesigned with data gathered from the extensive disco and plasma research." anchored = TRUE resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION - /obj/machinery/jukebox/public req_access = list() falloff_dist_offset = 10 @@ -55,7 +53,7 @@ return ..() /obj/machinery/jukebox/attackby(obj/item/O, mob/user, params) - if(!active && !(obj_flags & NO_DECONSTRUCTION)) + if(!active) if(O.tool_behaviour == TOOL_WRENCH) if(!anchored && !isinspace()) to_chat(user,span_notice("You secure [src] to the floor.")) diff --git a/modular_skyrat/modules/knives/knives.dm b/modular_skyrat/modules/knives/knives.dm index 4a7439d3e76..d177a3a24d9 100644 --- a/modular_skyrat/modules/knives/knives.dm +++ b/modular_skyrat/modules/knives/knives.dm @@ -24,25 +24,26 @@ slot_flags = ITEM_SLOT_POCKETS w_class = WEIGHT_CLASS_BULKY resistance_flags = FLAMMABLE + interaction_flags_click = NEED_DEXTERITY /obj/item/storage/belt/bowie_sheath/Initialize(mapload) . = ..() atom_storage.max_slots = 1 atom_storage.max_total_storage = WEIGHT_CLASS_BULKY atom_storage.set_holdable(list( - /obj/item/knife/bowie + /obj/item/knife/bowie, )) -/obj/item/storage/belt/bowie_sheath/AltClick(mob/user) - if(!user.can_perform_action(src, NEED_DEXTERITY)) - return +/obj/item/storage/belt/bowie_sheath/click_alt(mob/user) if(length(contents)) var/obj/item/knife = contents[1] user.visible_message(span_notice("[user] takes [knife] out of [src]."), span_notice("You take [knife] out of [src].")) user.put_in_hands(knife) update_appearance() + return CLICK_ACTION_SUCCESS else to_chat(user, span_warning("[src] is empty!")) + return CLICK_ACTION_BLOCKING /obj/item/storage/belt/bowie_sheath/update_icon_state() icon_state = initial(icon_state) diff --git a/modular_skyrat/modules/liquids/code/liquid_systems/liquid_controller.dm b/modular_skyrat/modules/liquids/code/liquid_systems/liquid_controller.dm index ed462fceaf5..b53cbc3bf04 100644 --- a/modular_skyrat/modules/liquids/code/liquid_systems/liquid_controller.dm +++ b/modular_skyrat/modules/liquids/code/liquid_systems/liquid_controller.dm @@ -112,10 +112,5 @@ SUBSYSTEM_DEF(liquids) if(T.lgroup) T.lgroup.amount_of_active_turfs-- -/client/proc/toggle_liquid_debug() - set category = "Debug" - set name = "Liquid Groups Color Debug" - set desc = "Liquid Groups Color Debug." - if(!holder) - return +ADMIN_VERB(toggle_liquid_debug, R_DEBUG, "Liquid Groups Color Debug", "Liquid Groups Color Debug.", ADMIN_CATEGORY_DEBUG) GLOB.liquid_debug_colors = !GLOB.liquid_debug_colors diff --git a/modular_skyrat/modules/liquids/code/liquid_systems/liquid_pump.dm b/modular_skyrat/modules/liquids/code/liquid_systems/liquid_pump.dm index 17d6c87f284..c97f06140c0 100644 --- a/modular_skyrat/modules/liquids/code/liquid_systems/liquid_pump.dm +++ b/modular_skyrat/modules/liquids/code/liquid_systems/liquid_pump.dm @@ -8,6 +8,7 @@ max_integrity = 500 anchored = FALSE resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF + interaction_flags_click = NEED_DEXTERITY /// How many reagents at maximum can it hold var/max_volume = 10000 /// Whether spewing reagents out, instead of siphoning them @@ -33,12 +34,11 @@ to_chat(user, span_notice("You turn [src] [turned_on ? "off" : "on"].")) toggle_working() -/obj/structure/liquid_pump/AltClick(mob/living/user) - if(!user.can_perform_action(src, NEED_DEXTERITY)) - return +/obj/structure/liquid_pump/click_alt(mob/living/user) to_chat(user, span_notice("You flick [src]'s spewing mode [spewing_mode ? "off" : "on"].")) spewing_mode = !spewing_mode update_icon() + return CLICK_ACTION_SUCCESS /obj/structure/liquid_pump/examine(mob/user) . = ..() diff --git a/modular_skyrat/modules/liquids/code/tools.dm b/modular_skyrat/modules/liquids/code/tools.dm index 1ee43b78a37..2252835f2b2 100644 --- a/modular_skyrat/modules/liquids/code/tools.dm +++ b/modular_skyrat/modules/liquids/code/tools.dm @@ -1,12 +1,8 @@ -/client/proc/spawn_liquid() - set category = "Admin.Fun" - set name = "Spawn Liquid" - set desc = "Spawns an amount of chosen liquid at your current location." - +ADMIN_VERB(spawn_liquid, R_ADMIN, "Spawn Liquid", "Spawns an amount of chosen liquid at your current location.", ADMIN_CATEGORY_FUN) var/choice var/valid_id while(!valid_id) - choice = tgui_input_text(usr, "Enter the ID of the reagent you want to add.", "Search reagents") + choice = tgui_input_text(user, "Enter the ID of the reagent you want to add.", "Search reagents") if(isnull(choice)) //Get me out of here! break if (!ispath(text2path(choice))) @@ -16,26 +12,21 @@ else valid_id = TRUE if(!valid_id) - to_chat(usr, span_warning("A reagent with that ID doesn't exist!")) + to_chat(user, span_warning("A reagent with that ID doesn't exist!")) if(!choice) return - var/volume = tgui_input_number(usr, "Volume:", "Choose volume") + var/volume = tgui_input_number(user, "Volume:", "Choose volume") if(!volume) return - var/turf/epicenter = get_turf(mob) + var/turf/epicenter = get_turf(user.mob) epicenter.add_liquid(choice, volume) - message_admins("[ADMIN_LOOKUPFLW(usr)] spawned liquid at [epicenter.loc] ([choice] - [volume]).") - log_admin("[key_name(usr)] spawned liquid at [epicenter.loc] ([choice] - [volume]).") + message_admins("[ADMIN_LOOKUPFLW(user)] spawned liquid at [epicenter.loc] ([choice] - [volume]).") + log_admin("[key_name(user)] spawned liquid at [epicenter.loc] ([choice] - [volume]).") -/client/proc/remove_liquid(turf/epicenter in world) - set name = "Remove Liquids" - set category = "Admin.Game" - set desc = "Fixes air in specified radius." - - var/range = tgui_input_number(usr, "Enter range:", "Range selection", 2) +ADMIN_VERB_AND_CONTEXT_MENU(remove_liquid, R_ADMIN, "Remove liquids", "Removes all liquids in specified radius.", ADMIN_CATEGORY_GAME, turf/epicenter in world) + var/range = tgui_input_number(user, "Enter range:", "Range selection", 2) for(var/obj/effect/abstract/liquid_turf/liquid in range(range, epicenter)) qdel(liquid, TRUE) - message_admins("[key_name_admin(usr)] removed liquids with range [range] in [epicenter.loc.name]") - log_game("[key_name_admin(usr)] removed liquids with range [range] in [epicenter.loc.name]") + message_admins("[key_name_admin(user)] removed liquids with range [range] in [epicenter.loc.name]") diff --git a/modular_skyrat/modules/lorecaster/code/story_manager.dm b/modular_skyrat/modules/lorecaster/code/story_manager.dm index 3b60915bb69..5bb613c7030 100644 --- a/modular_skyrat/modules/lorecaster/code/story_manager.dm +++ b/modular_skyrat/modules/lorecaster/code/story_manager.dm @@ -1,10 +1,4 @@ -/client/proc/lorecaster_story_manager() - set category = "Admin.Events" - set name = "Lorecaster Stories" - - if(!check_rights(R_ADMIN)) - return - +ADMIN_VERB(lorecaster_story_manager, R_ADMIN, "Lorecaster Stories", "Open the Lorecaster Story Manager.", ADMIN_CATEGORY_EVENTS) var/datum/story_manager_interface/ui = new(usr) ui.ui_interact(usr) diff --git a/modular_skyrat/modules/mapping/code/machinery.dm b/modular_skyrat/modules/mapping/code/machinery.dm index 53500a29628..04fc7cca5f2 100644 --- a/modular_skyrat/modules/mapping/code/machinery.dm +++ b/modular_skyrat/modules/mapping/code/machinery.dm @@ -13,9 +13,6 @@ /obj/item/gps/computer/space/wrench_act(mob/living/user, obj/item/I) . = ..() - if(obj_flags & NO_DECONSTRUCTION) - return TRUE - if(I.use_tool(src, user, 20, volume=50)) user.visible_message(span_warning("[user] disassembles [src]."), span_notice("You start to disassemble [src]..."), span_hear("You hear clanking and banging noises.")) diff --git a/modular_skyrat/modules/mapping/code/shuttles.dm b/modular_skyrat/modules/mapping/code/shuttles.dm index d50ae38bc5c..89d0aade9c7 100644 --- a/modular_skyrat/modules/mapping/code/shuttles.dm +++ b/modular_skyrat/modules/mapping/code/shuttles.dm @@ -69,7 +69,16 @@ shuttleId = "slaver_syndie" possible_destinations = "syndicate_ne;syndicate_nw;syndicate_n;syndicate_se;syndicate_sw;syndicate_s" resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION + +// previously NO_DECONSTRUCTION +/obj/machinery/computer/shuttle/slaver/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) + return NONE + +/obj/machinery/computer/shuttle/slaver/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct) + return NONE + +/obj/machinery/computer/shuttle/slaver/default_pry_open(obj/item/crowbar, close_after_pry = FALSE, open_density = FALSE, closed_density = TRUE) + return NONE /datum/map_template/shuttle/slaver_ship port_id = "slaver ship" diff --git a/modular_skyrat/modules/medical/code/anesthetic_machine.dm b/modular_skyrat/modules/medical/code/anesthetic_machine.dm index 69b1bab7b70..eb42dda946e 100644 --- a/modular_skyrat/modules/medical/code/anesthetic_machine.dm +++ b/modular_skyrat/modules/medical/code/anesthetic_machine.dm @@ -78,10 +78,9 @@ attached_tank = attacking_item update_icon() -/obj/machinery/anesthetic_machine/AltClick(mob/user) - . = ..() +/obj/machinery/anesthetic_machine/click_alt(mob/user) if(!attached_tank) - return + return CLICK_ACTION_BLOCKING attached_tank.forceMove(loc) to_chat(user, span_notice("You remove the [attached_tank].")) @@ -89,6 +88,7 @@ update_icon() if(mask_out) retract_mask() + return CLICK_ACTION_SUCCESS ///Retracts the attached_mask back into the machine /obj/machinery/anesthetic_machine/proc/retract_mask() diff --git a/modular_skyrat/modules/microfusion/code/_microfusion_defines.dm b/modular_skyrat/modules/microfusion/code/_microfusion_defines.dm index b44acde2567..d130ad30829 100644 --- a/modular_skyrat/modules/microfusion/code/_microfusion_defines.dm +++ b/modular_skyrat/modules/microfusion/code/_microfusion_defines.dm @@ -1,41 +1,8 @@ -/// The amount of cell charge drained during a drain failure. -#define MICROFUSION_CELL_DRAIN_FAILURE 500 -/// The heavy EMP range for when a cell suffers an EMP failure. -#define MICROFUSION_CELL_EMP_HEAVY_FAILURE 2 -/// The light EMP range for when a cell suffers an EMP failure. -#define MICROFUSION_CELL_EMP_LIGHT_FAILURE 4 -/// The radiation range for when a cell suffers a radiation failure. -#define MICROFUSION_CELL_RADIATION_RANGE_FAILURE 1 - -/// The lower most time for a microfusion cell meltdown. -#define MICROFUSION_CELL_FAILURE_LOWER (10 SECONDS) -/// The upper most time for a microfusion cell meltdown. -#define MICROFUSION_CELL_FAILURE_UPPER (15 SECONDS) - -/// A charge drain failure. -#define MICROFUSION_CELL_FAILURE_TYPE_CHARGE_DRAIN 1 -/// A small explosion failure. -#define MICROFUSION_CELL_FAILURE_TYPE_EXPLOSION 2 -/// EMP failure. -#define MICROFUSION_CELL_FAILURE_TYPE_EMP 3 -/// Radiation failure. -#define MICROFUSION_CELL_FAILURE_TYPE_RADIATION 4 - /// Returned when the phase emtiter process is successful. #define SHOT_SUCCESS "success" /// Returned when a gun is fired but there is no phase emitter. #define SHOT_FAILURE_NO_EMITTER "no phase emitter!" -/// The error message returned when the phase emitter is processed but damaged. -#define PHASE_FAILURE_DAMAGED "PHASE EMITTER: Emitter damaged!" -/// The error message returned when the phase emitter has reached it's htermal throttle. -#define PHASE_FAILURE_THROTTLE "PHASE EMITTER: Thermal throttle active!" - -/// The heat dissipation bonus of an emitter being in space! -#define PHASE_HEAT_DISSIPATION_BONUS_SPACE 30 -/// The heat dissipation bonus of an emitter being in air! -#define PHASE_HEAT_DISSIPATION_BONUS_AIR 10 - // Slot defines for the gun. /// The gun barrel slot. #define GUN_SLOT_BARREL "barrel" @@ -47,8 +14,3 @@ #define GUN_SLOT_UNIQUE "unique" /// Camo slot. Because why would you put four overlapping camos on your gun? #define GUN_SLOT_CAMO "camo" - -/// Max name size for changing names -#define GUN_MAX_NAME_CHARS 20 -/// Min name size for changing names -#define GUN_MIN_NAME_CHARS 3 diff --git a/modular_skyrat/modules/microfusion/code/microfusion_cell.dm b/modular_skyrat/modules/microfusion/code/microfusion_cell.dm index 09d403e3fa5..515dc89f174 100644 --- a/modular_skyrat/modules/microfusion/code/microfusion_cell.dm +++ b/modular_skyrat/modules/microfusion/code/microfusion_cell.dm @@ -6,6 +6,29 @@ Microfusion cells are small battery units that house controlled nuclear fusion w Essentially, power cells that malfunction if not used in an MCR, and should only be able to charge inside of one */ +/// The amount of cell charge drained during a drain failure. +#define MICROFUSION_CELL_DRAIN_FAILURE STANDARD_CELL_CHARGE * 0.5 +/// The heavy EMP range for when a cell suffers an EMP failure. +#define MICROFUSION_CELL_EMP_HEAVY_FAILURE 2 +/// The light EMP range for when a cell suffers an EMP failure. +#define MICROFUSION_CELL_EMP_LIGHT_FAILURE 4 +/// The radiation range for when a cell suffers a radiation failure. +#define MICROFUSION_CELL_RADIATION_RANGE_FAILURE 1 + +/// The lower most time for a microfusion cell meltdown. +#define MICROFUSION_CELL_FAILURE_LOWER (10 SECONDS) +/// The upper most time for a microfusion cell meltdown. +#define MICROFUSION_CELL_FAILURE_UPPER (15 SECONDS) + +/// A charge drain failure. +#define MICROFUSION_CELL_FAILURE_TYPE_CHARGE_DRAIN 1 +/// A small explosion failure. +#define MICROFUSION_CELL_FAILURE_TYPE_EXPLOSION 2 +/// EMP failure. +#define MICROFUSION_CELL_FAILURE_TYPE_EMP 3 +/// Radiation failure. +#define MICROFUSION_CELL_FAILURE_TYPE_RADIATION 4 + /obj/item/stock_parts/cell/microfusion //Just a standard cell. name = "microfusion cell" desc = "A standard-issue microfusion cell, produced by Micron Control Systems. For safety reasons, they cannot be charged unless they are inside of a compatible Micron Control Systems firearm." @@ -13,7 +36,7 @@ Essentially, power cells that malfunction if not used in an MCR, and should only charging_icon = "mf_in" //This is stored in cell.dmi in the aesthetics module icon_state = "microfusion" w_class = WEIGHT_CLASS_NORMAL - maxcharge = 1200 //12 shots + maxcharge = STANDARD_CELL_CHARGE chargerate = 0 //MF cells should be unable to recharge if they are not currently inside of an MCR microfusion_readout = TRUE empty = TRUE //MF cells should start empty @@ -153,7 +176,7 @@ Essentially, power cells that malfunction if not used in an MCR, and should only update_appearance() /obj/item/stock_parts/cell/microfusion/proc/inserted_into_weapon() - chargerate = 300 + chargerate = STANDARD_CELL_CHARGE * 0.2 /obj/item/stock_parts/cell/microfusion/proc/cell_removal_discharge() chargerate = 0 @@ -176,7 +199,7 @@ Essentially, power cells that malfunction if not used in an MCR, and should only name = "makeshift microfusion cell" desc = "An... Apparatus, comprised of an everyday aluminum can with several civilian-grade batteries tightly packed together and plugged in. This vaguely resembles a microfusion cell, if you tilt your head to a precise fifty degree angle. While the effects on enemy combatants may be dubious, it will certainly do incredible damage to the gun's warranty. What the hell were you thinking when you came up with this?" icon_state = "microfusion_makeshift" - maxcharge = 600 + maxcharge = STANDARD_CELL_CHARGE * 0.5 max_attachments = 0 /obj/item/stock_parts/cell/microfusion/makeshift/use(amount, force = FALSE) @@ -188,26 +211,39 @@ Essentially, power cells that malfunction if not used in an MCR, and should only name = "enhanced microfusion cell" desc = "A second generation microfusion cell, weighing about the same as the standard-issue cell and having the same space for attachments; however, it has a higher capacity." icon_state = "microfusion_enhanced" - maxcharge = 1500 + maxcharge = STANDARD_CELL_CHARGE * 1.4 /obj/item/stock_parts/cell/microfusion/advanced name = "advanced microfusion cell" desc = "A third generation microfusion cell, boasting a much higher shot count. Additionally, these come with support for up to three modifications to the cell itself." icon_state = "microfusion_advanced" - maxcharge = 1700 + maxcharge = STANDARD_CELL_CHARGE * 1.5 max_attachments = 3 /obj/item/stock_parts/cell/microfusion/bluespace name = "bluespace microfusion cell" desc = "A fourth generation microfusion cell, employing bluespace technology to store power in a medium that's bigger on the inside. This has capacity for four modifications to the cell." icon_state = "microfusion_bluespace" - maxcharge = 2000 + maxcharge = STANDARD_CELL_CHARGE * 1.6 max_attachments = 4 /obj/item/stock_parts/cell/microfusion/nanocarbon name = "nanocarbon fusion cell" desc = "This cell combines both top-of-the-line nanotech and advanced microfusion power to brute force the most common issue of Nanotrasen Asset Protection operatives, ammunition, through sheer volume. Intended for use with Nanotrasen-brand capacitor arrays only. Warranty void if dropped in toilet." icon_state = "microfusion_nanocarbon" - maxcharge = 30000 + maxcharge = STANDARD_CELL_CHARGE * 60 // Wanted to put 69 here to fit with the 420 but eh this werks too max_attachments = 420 + +#undef MICROFUSION_CELL_DRAIN_FAILURE +#undef MICROFUSION_CELL_EMP_HEAVY_FAILURE +#undef MICROFUSION_CELL_EMP_LIGHT_FAILURE +#undef MICROFUSION_CELL_RADIATION_RANGE_FAILURE + +#undef MICROFUSION_CELL_FAILURE_LOWER +#undef MICROFUSION_CELL_FAILURE_UPPER + +#undef MICROFUSION_CELL_FAILURE_TYPE_CHARGE_DRAIN +#undef MICROFUSION_CELL_FAILURE_TYPE_EXPLOSION +#undef MICROFUSION_CELL_FAILURE_TYPE_EMP +#undef MICROFUSION_CELL_FAILURE_TYPE_RADIATION diff --git a/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm b/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm index e242cebbc1c..6dce4269ef8 100644 --- a/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm +++ b/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm @@ -91,7 +91,7 @@ else cell = new(src) cell.parent_gun = src - cell.chargerate = 300 + cell.chargerate = STANDARD_CELL_CHARGE * 0.2 if(!dead_cell) cell.give(cell.maxcharge) if(phase_emitter_type) @@ -263,13 +263,12 @@ playsound(src, 'sound/items/crowbar.ogg', 70, TRUE) remove_emitter() -/obj/item/gun/microfusion/AltClick(mob/user) - . = ..() - if(can_interact(user)) - var/obj/item/microfusion_gun_attachment/to_remove = input(user, "Please select what part you'd like to remove.", "Remove attachment") as null|obj in sort_names(attachments) - if(!to_remove) - return - remove_attachment(to_remove, user) +/obj/item/gun/microfusion/click_alt(mob/user) + var/obj/item/microfusion_gun_attachment/to_remove = input(user, "Please select what part you'd like to remove.", "Remove attachment") as null|obj in sort_names(attachments) + if(!to_remove) + return CLICK_ACTION_BLOCKING + remove_attachment(to_remove, user) + return CLICK_ACTION_SUCCESS /obj/item/gun/microfusion/proc/remove_all_attachments() if(attachments.len) diff --git a/modular_skyrat/modules/microfusion/code/phase_emitter.dm b/modular_skyrat/modules/microfusion/code/phase_emitter.dm index f213ff4896f..eade9e3407b 100644 --- a/modular_skyrat/modules/microfusion/code/phase_emitter.dm +++ b/modular_skyrat/modules/microfusion/code/phase_emitter.dm @@ -2,6 +2,16 @@ * PHASE EMITTERS */ +/// The error message returned when the phase emitter is processed but damaged. +#define PHASE_FAILURE_DAMAGED "PHASE EMITTER: Emitter damaged!" +/// The error message returned when the phase emitter has reached it's htermal throttle. +#define PHASE_FAILURE_THROTTLE "PHASE EMITTER: Thermal throttle active!" + +/// The heat dissipation bonus of an emitter being in space! +#define PHASE_HEAT_DISSIPATION_BONUS_SPACE 30 +/// The heat dissipation bonus of an emitter being in air! +#define PHASE_HEAT_DISSIPATION_BONUS_AIR 10 + /* * Basically the heart of the gun, can be upgraded. */ @@ -212,3 +222,13 @@ cooling_system_rate = 60 integrity = 500 color = "#6966ff" + + +#undef PHASE_FAILURE_DAMAGED +#undef PHASE_FAILURE_THROTTLE + +#undef PHASE_HEAT_DISSIPATION_BONUS_SPACE +#undef PHASE_HEAT_DISSIPATION_BONUS_AIR + +#undef SHOT_SUCCESS +#undef SHOT_FAILURE_NO_EMITTER diff --git a/modular_skyrat/modules/microfusion/code/projectiles.dm b/modular_skyrat/modules/microfusion/code/projectiles.dm index 53f19941f8d..03849b456a2 100644 --- a/modular_skyrat/modules/microfusion/code/projectiles.dm +++ b/modular_skyrat/modules/microfusion/code/projectiles.dm @@ -5,7 +5,7 @@ /obj/item/ammo_casing/energy/laser/microfusion name = "microfusion energy lens" projectile_type = /obj/projectile/beam/laser/microfusion - e_cost = LASER_SHOTS(10, STANDARD_CELL_CHARGE) // 10 shots with a normal cell. + e_cost = LASER_SHOTS(12, STANDARD_CELL_CHARGE) select_name = "laser" fire_sound = 'modular_skyrat/modules/microfusion/sound/laser_1.ogg' fire_sound_volume = 100 diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm index 9d2fae9d311..ef18300ddab 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm @@ -72,20 +72,17 @@ "cyan" = image(icon = src.icon, icon_state = "mask_cyan_off")) // Using multitool on pole -/obj/item/clothing/mask/gas/bdsm_mask/AltClick(mob/user) +/obj/item/clothing/mask/gas/bdsm_mask/click_alt(mob/user) if(color_changed == FALSE) - if(.) - return var/choice = show_radial_menu(user, src, mask_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_mask_color = choice update_icon_state() update_icon() update_mob_action_buttonss() color_changed = TRUE - return - . = ..() + return CLICK_ACTION_SUCCESS // To check if we can change mask's model /obj/item/clothing/mask/gas/bdsm_mask/proc/check_menu(mob/living/user) @@ -321,6 +318,7 @@ volume = 50 possible_transfer_amounts = list(1, 2, 3, 4, 5, 10, 25, 50) list_reagents = list(/datum/reagent/drug/aphrodisiac/crocin = 50) + interaction_flags_click = NEED_DEXTERITY // Standard initialize code for filter /obj/item/reagent_containers/cup/lewd_filter/Initialize(mapload) @@ -337,11 +335,7 @@ addtimer(CALLBACK(reagents, TYPE_PROC_REF(/datum/reagents, trans_to), user, amount_per_transfer_from_this, TRUE, TRUE, FALSE, user, FALSE, INGEST), 0.5 SECONDS) // I just wanted to add 2th color variation. Because. -/obj/item/reagent_containers/cup/lewd_filter/AltClick(mob/user) - // Catch first AltClick and open reskin menu - if(unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY)) - reskin_obj(user) - return +/obj/item/reagent_containers/cup/lewd_filter/click_alt(mob/user) // After reskin all clicks go normal, but we can't change the flow rate if mask on and equipped var/obj/item/clothing/mask/gas/bdsm_mask/worn_mask = user.get_item_by_slot(ITEM_SLOT_MASK) if(worn_mask) @@ -350,8 +344,8 @@ if(worn_mask.mask_on == TRUE) if(istype(src, /obj/item/reagent_containers/cup/lewd_filter)) to_chat(user, span_warning("You can't change the flow rate of the valve while the mask is on!")) - return - . = ..() + return CLICK_ACTION_BLOCKING + return ..() // Filter click handling /obj/item/reagent_containers/cup/lewd_filter/attack_hand(mob/user) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/corset.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/corset.dm index 821e056bb94..f537d9166f8 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/corset.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/corset.dm @@ -17,10 +17,11 @@ /// Has it been laced tightly? var/laced_tight = FALSE -/obj/item/clothing/suit/corset/AltClick(mob/user) +/obj/item/clothing/suit/corset/click_alt(mob/user) laced_tight = !laced_tight to_chat(user, span_notice("You [laced_tight ? "tighten" : "loosen"] the corset, making it far [laced_tight ? "harder" : "easier"] to breathe.")) play_lewd_sound(user, laced_tight ? 'sound/items/handling/cloth_pickup.ogg' : 'sound/items/handling/cloth_drop.ogg', 40, TRUE) + . = CLICK_ACTION_SUCCESS if(laced_tight) slowdown = TIGHT_SLOWDOWN return diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/deprivation_helmet.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/deprivation_helmet.dm index a6188a546e4..7bcad0d4879 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/deprivation_helmet.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/deprivation_helmet.dm @@ -129,20 +129,18 @@ "tealn" = image(icon = src.icon, icon_state = "dephelmet_tealn")) // To change model -/obj/item/clothing/head/deprivation_helmet/AltClick(mob/user) +/obj/item/clothing/head/deprivation_helmet/click_alt(mob/user) if(color_changed == FALSE) - . = ..() - if(.) - return var/choice = show_radial_menu(user, src, helmet_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_helmet_color = choice update_icon() update_mob_action_buttonss() color_changed = TRUE + return CLICK_ACTION_SUCCESS else - return + return CLICK_ACTION_BLOCKING /obj/item/clothing/head/deprivation_helmet/proc/update_mob_action_buttonss() var/datum/action/item_action/action_button diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/hypnogoggles.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/hypnogoggles.dm index 554cfab890c..5150f7a539b 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/hypnogoggles.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/hypnogoggles.dm @@ -58,18 +58,16 @@ "teal" = image(icon = src.icon, icon_state = "hypnogoggles_teal")) //to change model -/obj/item/clothing/glasses/hypno/AltClick(mob/user) +/obj/item/clothing/glasses/hypno/click_alt(mob/user) if(color_changed) - return - . = ..() - if(.) - return + return CLICK_ACTION_BLOCKING var/choice = show_radial_menu(user, src, hypnogoggles_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_hypnogoggles_color = choice update_icon() color_changed = TRUE + return CLICK_ACTION_SUCCESS //to check if we can change kinkphones's model /obj/item/clothing/glasses/hypno/proc/check_menu(mob/living/user) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kink_collars.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kink_collars.dm index aa8ff23f1b6..025d267680e 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kink_collars.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kink_collars.dm @@ -35,10 +35,7 @@ body_parts_covered = NECK slot_flags = ITEM_SLOT_NECK w_class = WEIGHT_CLASS_SMALL - /// What the name on the tag is - var/tagname = null - /// Item path of on-init creation in the collar's storage - var/treat_path = /obj/item/food/cookie + interaction_flags_click = NEED_DEXTERITY unique_reskin = list("Cyan" = "collar_cyan", "Yellow" = "collar_yellow", "Green" = "collar_green", @@ -50,6 +47,10 @@ "Black" = "collar_black", "Black-teal" = "collar_tealblack", "Spike" = "collar_spike") + /// What the name on the tag is + var/tagname = null + /// Item path of on-init creation in the collar's storage + var/treat_path = /obj/item/food/cookie //spawn thing in collar @@ -66,13 +67,6 @@ var/obj/item/key/kink_collar/collar_key = key collar_key.key_id = id -//reskin code - -/obj/item/clothing/neck/kink_collar/AltClick(mob/user) - . = ..() - if(unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY)) - reskin_obj(user) - //rename collar code /obj/item/clothing/neck/kink_collar/attack_self(mob/user) @@ -90,10 +84,7 @@ worn_icon = 'modular_skyrat/modules/modular_items/lewd_items/icons/mob/lewd_clothing/lewd_neck.dmi' icon_state = "lock_collar_cyan" treat_path = /obj/item/key/kink_collar - /// If the collar is currently locked - var/locked = FALSE - /// If the collar has been broken or not - var/broken = FALSE + interaction_flags_click = NEED_DEXTERITY unique_reskin = list("Cyan" = "lock_collar_cyan", "Yellow" = "lock_collar_yellow", "Green" = "lock_collar_green", @@ -105,6 +96,10 @@ "Black" = "lock_collar_black", "Black-teal" = "lock_collar_tealblack", "Spike" = "lock_collar_spike") + /// If the collar is currently locked + var/locked = FALSE + /// If the collar has been broken or not + var/broken = FALSE /obj/item/clothing/neck/kink_collar/locked/Initialize(mapload) . = ..() @@ -112,13 +107,6 @@ //spawn thing in collar -//reskin code - -/obj/item/clothing/neck/kink_collar/locked/AltClick(mob/user) - . = ..() - if(unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY)) - reskin_obj(user) - //locking or unlocking collar code /obj/item/clothing/neck/kink_collar/locked/proc/IsLocked(to_lock, mob/user) @@ -176,6 +164,7 @@ icon = 'modular_skyrat/modules/modular_items/lewd_items/icons/obj/lewd_items/lewd_items.dmi' icon_state = "collar_key_metal" base_icon_state = "collar_key" + interaction_flags_click = NEED_DEXTERITY /// The name inscribed on the key var/keyname = null /// The ID of the key to pair with a collar. Will normally be the ref of the collar @@ -192,12 +181,6 @@ "Metal" = "collar_key_metal", "Black-teal" = "collar_key_tealblack") -//changing color of key in case if we using multiple collars -/obj/item/key/kink_collar/AltClick(mob/user) - . = ..() - if(unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY)) - reskin_obj(user) - //changing name of key in case if we using multiple collars with same color /obj/item/key/kink_collar/attack_self(mob/user) keyname = stripped_input(user, "Would you like to change the name on the key?", "Renaming key", "Key", MAX_NAME_LEN) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_blindfold.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_blindfold.dm index 40a716f3175..6e1674fc87f 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_blindfold.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_blindfold.dm @@ -22,19 +22,16 @@ "teal" = image(icon = src.icon, icon_state = "kblindfold_teal")) //to change model -/obj/item/clothing/glasses/blindfold/kinky/AltClick(mob/user) +/obj/item/clothing/glasses/blindfold/kinky/click_alt(mob/user) if(color_changed) - return - . = ..() - if(.) - return + return CLICK_ACTION_BLOCKING var/choice = show_radial_menu(user, src, kinkfold_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_kinkfold_color = choice update_icon() color_changed = TRUE - + return CLICK_ACTION_SUCCESS /// to check if we can change kinkphones's model /obj/item/clothing/glasses/blindfold/kinky/proc/check_menu(mob/living/user) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_headphones.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_headphones.dm index eb4ed5bf142..8e73ea7d434 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_headphones.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_headphones.dm @@ -28,18 +28,16 @@ "teal" = image(icon = src.icon, icon_state = "kinkphones_teal_on")) //to change model -/obj/item/clothing/ears/kinky_headphones/AltClick(mob/user) +/obj/item/clothing/ears/kinky_headphones/click_alt(mob/user) if(color_changed) - return - . = ..() - if(.) - return + return CLICK_ACTION_BLOCKING var/choice = show_radial_menu(user, src, kinkphones_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_kinkphones_color = choice update_icon() color_changed = TRUE + return CLICK_ACTION_SUCCESS /// to check if we can change kinkphones's model /obj/item/clothing/ears/kinky_headphones/proc/check_menu(mob/living/user) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_sleepbag.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_sleepbag.dm index 2f1588738cb..43e2ea0c904 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_sleepbag.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/kinky_sleepbag.dm @@ -48,23 +48,21 @@ "deflated" = image(icon = src.icon, icon_state = "sleepbag_teal_deflated_folded")) //to change model -/obj/item/clothing/suit/straight_jacket/kinky_sleepbag/AltClick(mob/user) +/obj/item/clothing/suit/straight_jacket/kinky_sleepbag/click_alt(mob/user) var/mob/living/carbon/human/clicking_human = user if(istype(clicking_human.wear_suit, /obj/item/clothing/suit/straight_jacket/kinky_sleepbag)) to_chat(user, span_warning("Your hands are stuck, you can't do this!")) - return FALSE + return CLICK_ACTION_BLOCKING switch(color_changed) if(FALSE) - . = ..() - if(.) - return var/choice = show_radial_menu(user, src, bag_colors, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING bag_color = choice update_icon() update_icon_state() color_changed = TRUE + return CLICK_ACTION_SUCCESS if(TRUE) if(bag_state == "deflated") @@ -72,8 +70,10 @@ to_chat(user, span_notice("The sleeping bag now is [bag_fold? "folded." : "unfolded."]")) update_icon() update_icon_state() + return CLICK_ACTION_SUCCESS else to_chat(user, span_notice("You can't fold the bag while it's inflated!")) + return CLICK_ACTION_BLOCKING /obj/item/clothing/suit/straight_jacket/kinky_sleepbag/proc/check_menu(mob/living/user) if(!istype(user)) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/lewd_maid.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/lewd_maid.dm index 00caec39977..53b01b6699e 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/lewd_maid.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/lewd_maid.dm @@ -48,18 +48,16 @@ "yellow" = image (icon = src.icon, icon_state = "lewdapron_yellow")) //to change model -/obj/item/clothing/accessory/lewdapron/AltClick(mob/user) +/obj/item/clothing/accessory/lewdapron/click_alt(mob/user) if(color_changed) - return - . = ..() - if(.) - return + return CLICK_ACTION_BLOCKING var/choice = show_radial_menu(user, src, apron_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_color = choice update_icon() color_changed = TRUE + return CLICK_ACTION_SUCCESS /// to check if we can change kinkphones's model /obj/item/clothing/accessory/lewdapron/proc/check_menu(mob/living/user) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shackles.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shackles.dm index e062af59494..5201bb02a35 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shackles.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shackles.dm @@ -33,19 +33,17 @@ "metal" = image (icon = src.icon, icon_state = "shackles_metal")) //to change model -/obj/item/clothing/suit/straight_jacket/shackles/AltClick(mob/user) - if(color_changed == FALSE) - . = ..() - if(.) - return - var/choice = show_radial_menu(user, src, shackles_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) - if(!choice) - return FALSE - current_color = choice - update_icon() - color_changed = TRUE - else - return +/obj/item/clothing/suit/straight_jacket/shackles/click_alt(mob/user) + if(color_changed) + return CLICK_ACTION_BLOCKING + + var/choice = show_radial_menu(user, src, shackles_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) + if(!choice) + return CLICK_ACTION_BLOCKING + current_color = choice + update_icon() + color_changed = TRUE + return CLICK_ACTION_SUCCESS //to check if we can change shackles' model /obj/item/clothing/suit/straight_jacket/shackles/proc/check_menu(mob/living/user) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shibari_worn_uniform.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shibari_worn_uniform.dm index b248a0aca88..866526dea48 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shibari_worn_uniform.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/shibari_worn_uniform.dm @@ -60,13 +60,12 @@ . = ..() AddElement(/datum/element/update_icon_updates_onmob) -/obj/item/clothing/under/shibari/AltClick(mob/user) - . = ..() +/obj/item/clothing/under/shibari/click_alt(mob/user) if(!ishuman(loc)) - return + return CLICK_ACTION_BLOCKING var/mob/living/carbon/human/hooman = loc if(user == hooman) - return + return CLICK_ACTION_BLOCKING switch(tightness) if(SHIBARI_TIGHTNESS_LOW) tightness = SHIBARI_TIGHTNESS_MED @@ -74,6 +73,7 @@ tightness = SHIBARI_TIGHTNESS_HIGH if(SHIBARI_TIGHTNESS_HIGH) tightness = SHIBARI_TIGHTNESS_LOW + return CLICK_ACTION_SUCCESS /obj/item/clothing/under/shibari/process(seconds_per_tick) if(!ishuman(loc)) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/strapon.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/strapon.dm index ec2fc7c0d9b..a7e1182d324 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/strapon.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/strapon.dm @@ -23,19 +23,16 @@ "human" = image (icon = src.icon, icon_state = "strapon_human")) //to change model -/obj/item/clothing/strapon/AltClick(mob/user) - if(type_changed == FALSE) - . = ..() - if(.) - return - var/choice = show_radial_menu(user, src, strapon_types, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) - if(!choice) - return FALSE - strapon_type = choice - update_icon() - type_changed = TRUE - else - return +/obj/item/clothing/strapon/click_alt(mob/user) + if(type_changed) + return CLICK_ACTION_BLOCKING + var/choice = show_radial_menu(user, src, strapon_types, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) + if(!choice) + return CLICK_ACTION_BLOCKING + strapon_type = choice + update_icon() + type_changed = TRUE + return CLICK_ACTION_SUCCESS //Check if we can change strapon's model /obj/item/clothing/strapon/proc/check_menu(mob/living/user) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/stripper_outfit.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/stripper_outfit.dm index 545748165c4..f2de5f7f900 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/stripper_outfit.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/stripper_outfit.dm @@ -11,6 +11,7 @@ can_adjust = FALSE icon_state = "stripper_cyan" inhand_icon_state = "b_suit" + interaction_flags_click = NEED_DEXTERITY unique_reskin = list("Cyan" = "stripper_cyan", "Yellow" = "stripper_yellow", "Green" = "stripper_green", @@ -21,8 +22,3 @@ "Purple" = "stripper_purple", "Black" = "stripper_black", "Black-teal" = "stripper_tealblack") - -/obj/item/clothing/under/stripper_outfit/AltClick(mob/user) - . = ..() - if(unique_reskin && !current_skin && user.can_perform_action(src, NEED_DEXTERITY)) - reskin_obj(user) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/attachable_vibrator.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/attachable_vibrator.dm index 13423a26016..1db92a08430 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/attachable_vibrator.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/attachable_vibrator.dm @@ -39,11 +39,8 @@ "pink" = image(icon = src.icon, icon_state = "[initial(base_icon_state)]_pink_low[(istype(src, /obj/item/clothing/sextoy/eggvib/signalvib)) ? "_on" : ""]"), "teal" = image(icon = src.icon, icon_state = "[initial(base_icon_state)]_teal_low[(istype(src, /obj/item/clothing/sextoy/eggvib/signalvib)) ? "_on" : ""]")) -/obj/item/clothing/sextoy/eggvib/AltClick(mob/user) +/obj/item/clothing/sextoy/eggvib/click_alt(mob/user) if(!color_changed) - . = ..() - if(.) - return var/choice = show_radial_menu(user, src, vib_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) return FALSE @@ -63,6 +60,7 @@ to_chat(user, span_notice("You turn off the vibrating egg. Fun time's over.")) update_icon() update_icon_state() + return CLICK_ACTION_SUCCESS /obj/item/clothing/sextoy/eggvib/Initialize(mapload) . = ..() @@ -190,18 +188,18 @@ //arousal stuff -/obj/item/clothing/sextoy/eggvib/signalvib/AltClick(mob/user) +/obj/item/clothing/sextoy/eggvib/signalvib/click_alt(mob/user) if(!color_changed) var/choice = show_radial_menu(user, src, vib_designs, custom_check = CALLBACK(src, /obj/item/clothing/sextoy/proc/check_menu, user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_color = choice update_icon() color_changed = TRUE else if(!toy_on) - to_chat(usr, span_notice("You can't switch modes while the vibrating egg is turned off!")) - return + to_chat(user, span_notice("You can't switch modes while the vibrating egg is turned off!")) + return CLICK_ACTION_BLOCKING toggle_mode() soundloop1.stop() soundloop2.stop() @@ -218,6 +216,7 @@ soundloop3.start() update_icon() update_icon_state() + return CLICK_ACTION_SUCCESS /obj/item/clothing/sextoy/eggvib/signalvib/receive_signal(datum/signal/signal) if(!signal || signal.data["code"] != code) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/buttplug.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/buttplug.dm index 7297472b8da..5bcc5129e03 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/buttplug.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/buttplug.dm @@ -40,31 +40,27 @@ "medium" = image(icon = src.icon, icon_state = "buttplug_pink_medium"), "big" = image(icon = src.icon, icon_state = "buttplug_pink_big")) -/obj/item/clothing/sextoy/buttplug/AltClick(mob/user) +/obj/item/clothing/sextoy/buttplug/click_alt(mob/user) if(!color_changed) - . = ..() - if(.) - return var/choice = show_radial_menu(user, src, buttplug_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_color = choice update_icon() if(choice == "green") set_light(0.25) update_light() color_changed = TRUE + return CLICK_ACTION_SUCCESS else if(form_changed == FALSE) - . = ..() - if(.) - return var/choice = show_radial_menu(user, src, buttplug_forms, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_size = choice update_icon() form_changed = TRUE + return CLICK_ACTION_SUCCESS /obj/item/clothing/sextoy/buttplug/Initialize(mapload) . = ..() diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/dildo.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/dildo.dm index c7256be1610..9feeb963a09 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/dildo.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/dildo.dm @@ -41,18 +41,16 @@ "human" = image(icon = src.icon, icon_state = "[base_icon_state]_human"), "tentacle" = image(icon = src.icon, icon_state = "[base_icon_state]_tentacle")) -/obj/item/clothing/sextoy/dildo/AltClick(mob/user) +/obj/item/clothing/sextoy/dildo/click_alt(mob/user) if(color_changed) - return - . = ..() - if(.) - return + return CLICK_ACTION_BLOCKING var/choice = show_radial_menu(user, src, dildo_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_type = choice update_icon() color_changed = TRUE + return CLICK_ACTION_SUCCESS /obj/item/clothing/sextoy/dildo/Initialize(mapload) . = ..() @@ -209,23 +207,22 @@ GLOBAL_LIST_INIT(dildo_colors, list(//mostly neon colors "medium" = image(icon = src.icon, icon_state = "[base_icon_state]_medium"), "big" = image(icon = src.icon, icon_state = "[base_icon_state]_big")) -/obj/item/clothing/sextoy/dildo/custom_dildo/AltClick(mob/living/user) +/obj/item/clothing/sextoy/dildo/custom_dildo/click_alt(mob/living/user) if(!size_changed) var/choice = show_radial_menu(user, src, dildo_sizes, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING poly_size = choice update_icon() size_changed = TRUE - else if(color_changed) - return + return CLICK_ACTION_BLOCKING if(!istype(user) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) - return + return CLICK_ACTION_BLOCKING customize(user) color_changed = TRUE - return TRUE + return CLICK_ACTION_SUCCESS /obj/item/clothing/sextoy/dildo/custom_dildo/Initialize(mapload) . = ..() @@ -292,8 +289,8 @@ GLOBAL_LIST_INIT(dildo_colors, list(//mostly neon colors /obj/item/clothing/sextoy/dildo/double_dildo/populate_dildo_designs() return -/obj/item/clothing/sextoy/dildo/double_dildo/AltClick(mob/user) - return +/obj/item/clothing/sextoy/dildo/double_dildo/click_alt(mob/user) + return NONE /obj/item/clothing/sextoy/dildo/double_dildo/lewd_equipped(mob/living/carbon/human/user, slot, initial) . = ..() diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/fleshlight.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/fleshlight.dm index 3099ce8c3d2..02b25ecefd4 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/fleshlight.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/fleshlight.dm @@ -39,18 +39,16 @@ icon_state = "[base_icon_state]_[current_color]" inhand_icon_state = "[base_icon_state]_[current_color]" -/obj/item/clothing/sextoy/fleshlight/AltClick(mob/user) +/obj/item/clothing/sextoy/fleshlight/click_alt(mob/user) if(color_changed) - return - . = ..() - if(.) - return + return CLICK_ACTION_BLOCKING var/choice = show_radial_menu(user, src, fleshlight_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_color = choice update_icon() color_changed = TRUE + return CLICK_ACTION_SUCCESS /obj/item/clothing/sextoy/fleshlight/attack(mob/living/carbon/human/target, mob/living/carbon/human/user) . = ..() diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/kinky_shocker.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/kinky_shocker.dm index 6e67c51fe34..21328dcea3a 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/kinky_shocker.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/kinky_shocker.dm @@ -69,8 +69,9 @@ to_chat(user, span_notice("You install a cell in [src].")) update_appearance() -/obj/item/kinky_shocker/AltClick(mob/user) +/obj/item/kinky_shocker/click_alt(mob/user) tryremovecell(user) + return CLICK_ACTION_SUCCESS /obj/item/kinky_shocker/proc/tryremovecell(mob/user) if(!(cell && can_remove_cell)) @@ -81,6 +82,7 @@ to_chat(user, span_notice("You remove the cell from [src].")) shocker_on = FALSE update_appearance() + return CLICK_ACTION_SUCCESS /obj/item/kinky_shocker/attack_self(mob/user) toggle_shocker(user) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/leather_whip.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/leather_whip.dm index 83ac7d1ca0b..83beedd5605 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/leather_whip.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/leather_whip.dm @@ -88,32 +88,27 @@ update_overlays() //to change color -/obj/item/clothing/mask/leatherwhip/AltClick(mob/user) +/obj/item/clothing/mask/leatherwhip/click_alt(mob/user) if(!color_changed) - . = ..() - if(.) - return var/choice = show_radial_menu(user, src, whip_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_whip_color = choice update_icon() update_icon_state() color_changed = TRUE - + return CLICK_ACTION_SUCCESS else if(form_changed) - return - . = ..() - if(.) - return + return CLICK_ACTION_BLOCKING var/choice = show_radial_menu(user, src, whip_forms, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_whip_form = choice update_icon() update_icon_state() form_changed = TRUE + return CLICK_ACTION_SUCCESS /// A check to see if the radial menu can be used /obj/item/clothing/mask/leatherwhip/proc/check_menu(mob/living/user) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/spanking_pad.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/spanking_pad.dm index dcab8ba06e4..facf60ea273 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/spanking_pad.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/spanking_pad.dm @@ -43,19 +43,17 @@ icon_state = "[base_icon_state]_[current_color]" inhand_icon_state = "[base_icon_state]_[current_color]" -/obj/item/spanking_pad/AltClick(mob/user) +/obj/item/spanking_pad/click_alt(mob/user) if(color_changed) - return - . = ..() - if(.) - return + return CLICK_ACTION_BLOCKING var/choice = show_radial_menu(user, src, spankpad_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_color = choice update_icon_state() update_icon() color_changed = TRUE + return CLICK_ACTION_SUCCESS /obj/item/spanking_pad/attack(mob/living/carbon/human/target, mob/living/carbon/human/user) . = ..() diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/torture_candle.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/torture_candle.dm index fe0582abea5..3d24a3b649e 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/torture_candle.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/torture_candle.dm @@ -108,23 +108,24 @@ open_flame() update_brightness() -/obj/item/bdsm_candle/AltClick(mob/user) - . = ..() +/obj/item/bdsm_candle/click_alt(mob/user) if(!lit) if(color_changed) - return + return CLICK_ACTION_BLOCKING var/choice = show_radial_menu(user, src, candle_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_color = choice light_color = candlelights[choice] update_icon() update_brightness() color_changed = TRUE + return CLICK_ACTION_SUCCESS else if(!put_out_candle()) - return + return CLICK_ACTION_BLOCKING user.visible_message(span_notice("[user] snuffs [src].")) + return CLICK_ACTION_SUCCESS /* * WAX DROPPING diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibrator.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibrator.dm index c8174fe64e5..35b8ce8855e 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibrator.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibrator.dm @@ -42,19 +42,17 @@ "yellow" = image(icon = src.icon, icon_state = "vibrator_yellow_low"), "green" = image(icon = src.icon, icon_state = "vibrator_green_low")) -/obj/item/clothing/sextoy/vibrator/AltClick(mob/user) +/obj/item/clothing/sextoy/vibrator/click_alt(mob/user) if(color_changed) return - . = ..() - if(.) - return var/choice = show_radial_menu(user, src, vibrator_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_color = choice update_icon_state() update_icon() color_changed = TRUE + return CLICK_ACTION_SUCCESS /obj/item/clothing/sextoy/vibrator/Initialize(mapload) . = ..() diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibroring.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibroring.dm index dd531231d24..03b1ca6ade5 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibroring.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/vibroring.dm @@ -36,18 +36,16 @@ "pink" = image(icon = src.icon, icon_state = "vibroring_pink_off"), "teal" = image(icon = src.icon, icon_state = "vibroring_teal_off")) -/obj/item/clothing/sextoy/vibroring/AltClick(mob/user) +/obj/item/clothing/sextoy/vibroring/click_alt(mob/user) if(color_changed) - return - . = ..() - if(.) - return + return CLICK_ACTION_BLOCKING var/choice = show_radial_menu(user, src, vibroring_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_color = choice update_icon() color_changed = TRUE + return CLICK_ACTION_SUCCESS /obj/item/clothing/sextoy/vibroring/Initialize(mapload) . = ..() diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/milking_machine.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/milking_machine.dm index 25dba7d3508..3833fdb8edb 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/milking_machine.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/milking_machine.dm @@ -16,7 +16,6 @@ icon_state = "milking_pink_off" max_buckled_mobs = 1 item_chair = null - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION max_integrity = 75 var/static/list/milkingmachine_designs @@ -67,33 +66,6 @@ var/mutable_appearance/organ_overlay var/organ_overlay_new_icon_state = "" // Organ overlay update optimization -// Additional examine text -/obj/structure/chair/milking_machine/examine(mob/user) - . = ..() - . += span_notice("What are these metal mounts on the armrests for...?") - -/obj/structure/chair/milking_machine/Destroy() - if(current_mob) - if(current_mob.handcuffed) - current_mob.handcuffed.dropped(current_mob) - current_mob.set_handcuffed(null) - current_mob.update_abstract_handcuffed() - current_mob.layer = initial(current_mob.layer) - - if(beaker) - qdel(beaker) - beaker = null - - current_selected_organ = null - current_mob = null - current_breasts = null - current_testicles = null - current_vagina = null - - STOP_PROCESSING(SSobj, src) - unbuckle_all_mobs() - return ..() - // Object initialization /obj/structure/chair/milking_machine/Initialize(mapload) . = ..() @@ -124,6 +96,37 @@ populate_milkingmachine_designs() START_PROCESSING(SSobj, src) +// Additional examine text +/obj/structure/chair/milking_machine/examine(mob/user) + . = ..() + . += span_notice("What are these metal mounts on the armrests for...?") + +/obj/structure/chair/milking_machine/Destroy() + if(current_mob) + if(current_mob.handcuffed) + current_mob.handcuffed.dropped(current_mob) + current_mob.set_handcuffed(null) + current_mob.update_abstract_handcuffed() + current_mob.layer = initial(current_mob.layer) + + if(beaker) + qdel(beaker) + beaker = null + + current_selected_organ = null + current_mob = null + current_breasts = null + current_testicles = null + current_vagina = null + + STOP_PROCESSING(SSobj, src) + unbuckle_all_mobs() + return ..() + +// previously NO_DECONSTRUCTION +/obj/structure/chair/milking_machine/wrench_act_secondary(mob/living/user, obj/item/weapon) + return NONE + /* * APPEARANCE MANAGEMENT */ @@ -307,7 +310,7 @@ return FALSE replace_beaker(user, used_container) - updateUsrDialog() + SStgui.update_uis(src) return TRUE // Beaker change handler @@ -583,7 +586,7 @@ data["current_vagina"] = current_vagina = null data["machine_color"] = machine_color - updateUsrDialog() + SStgui.update_uis(src) return data // User action handler in the interface diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/bdsm_furniture.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/bdsm_furniture.dm index 9e46e1d018d..b6baa6d42f2 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/bdsm_furniture.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/bdsm_furniture.dm @@ -7,7 +7,6 @@ icon = 'modular_skyrat/modules/modular_items/lewd_items/icons/obj/lewd_structures/bdsm_furniture.dmi' icon_state = "bdsm_bed" max_integrity = 50 - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION /obj/item/bdsm_bed_kit name = "bdsm bed construction kit" @@ -41,6 +40,10 @@ . = ..() . += span_purple("[src] can be assembled by using Ctrl+Shift+Click while [src] is on the floor.") +// previously NO_DECONSTRUCTION +/obj/structure/bed/bdsm_bed/wrench_act_secondary(mob/living/user, obj/item/weapon) + return NONE + /obj/structure/bed/bdsm_bed/post_buckle_mob(mob/living/affected_mob) density = TRUE //Push them up from the normal lying position diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/construction.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/construction.dm index cc3ed2cdce8..7d35be6c12f 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/construction.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/construction.dm @@ -3,7 +3,7 @@ name = "construction kit" desc = "Used for constructing various things" w_class = WEIGHT_CLASS_BULKY - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION + obj_flags = CAN_BE_HIT throwforce = 0 ///What is the path for the resulting structure generating by using this item? var/obj/structure/resulting_structure = /obj/structure/chair diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/dancing_pole.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/dancing_pole.dm index e88b76206b9..6ba55958fe6 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/dancing_pole.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/dancing_pole.dm @@ -31,7 +31,8 @@ "green" = COLOR_GREEN, "white" = COLOR_WHITE, ) - + /// Is the pole in use currently? + var/pole_in_use /obj/structure/stripper_pole/examine(mob/user) . = ..() @@ -65,13 +66,14 @@ // Alt-click to turn the lights on or off. -/obj/structure/stripper_pole/AltClick(mob/user) +/obj/structure/stripper_pole/click_alt(mob/user) lights_enabled = !lights_enabled balloon_alert(user, "lights [lights_enabled ? "on" : "off"]") playsound(user, lights_enabled ? 'sound/weapons/magin.ogg' : 'sound/weapons/magout.ogg', 40, TRUE) update_icon_state() update_icon() update_brightness() + return CLICK_ACTION_SUCCESS /obj/structure/stripper_pole/Initialize(mapload) @@ -98,17 +100,17 @@ . = ..() if(.) return - if(obj_flags & IN_USE) + if(pole_in_use) balloon_alert(user, "already in use!") return - obj_flags |= IN_USE + pole_in_use = TRUE dancer = user user.setDir(SOUTH) user.Stun(10 SECONDS) user.forceMove(loc) user.visible_message(pick(span_purple("[user] dances on [src]!"), span_purple("[user] flexes their hip-moving skills on [src]!"))) dance_animate(user) - obj_flags &= ~IN_USE + pole_in_use = FALSE user.pixel_y = 0 user.pixel_z = pseudo_z_axis //incase we are off it when we jump on! dancer = null diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/pillow.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/pillow.dm index 0ac4d57fafb..7ee77500f7a 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/pillow.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/pillow.dm @@ -34,32 +34,28 @@ "square" = image (icon = src.icon, icon_state = "pillow_pink_square"), "round" = image(icon = src.icon, icon_state = "pillow_pink_round")) -/obj/item/fancy_pillow/AltClick(mob/user) - if(color_changed == FALSE) - . = ..() - if(.) - return +/obj/item/fancy_pillow/click_alt(mob/user) + if(!color_changed) var/choice = show_radial_menu(user, src, pillow_colors, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) - return FALSE + return CLICK_ACTION_BLOCKING current_color = choice update_icon() color_changed = TRUE update_icon_state() - if(color_changed == TRUE) - if(form_changed == FALSE) - . = ..() - if(.) - return - var/choice = show_radial_menu(user, src, pillow_forms, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) - if(!choice) - return FALSE - current_form = choice - update_icon() - form_changed = TRUE - update_icon_state() + return CLICK_ACTION_SUCCESS else - return + if(form_changed) + return CLICK_ACTION_BLOCKING + var/choice = show_radial_menu(user, src, pillow_forms, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) + if(!choice) + return CLICK_ACTION_BLOCKING + current_form = choice + update_icon() + form_changed = TRUE + update_icon_state() + return CLICK_ACTION_SUCCESS + //to check if we can change pillow's model /obj/item/fancy_pillow/proc/check_menu(mob/living/user) @@ -185,7 +181,7 @@ //picking up the pillow -/obj/structure/bed/pillow_tiny/AltClick(mob/user) +/obj/structure/bed/pillow_tiny/click_alt(mob/user) to_chat(user, span_notice("You pick up [src].")) var/obj/item/fancy_pillow/taken_pillow = new() user.put_in_hands(taken_pillow) @@ -198,6 +194,7 @@ taken_pillow.update_icon_state() taken_pillow.update_icon() qdel(src) + return CLICK_ACTION_SUCCESS //when we lay on it @@ -308,7 +305,7 @@ icon_state = "[base_icon_state]_[current_color]" //Removing pillow from a pile -/obj/structure/chair/pillow_small/AltClick(mob/user) +/obj/structure/chair/pillow_small/click_alt(mob/user) to_chat(user, span_notice("You take [src] from the pile.")) var/obj/item/fancy_pillow/taken_pillow = new() var/obj/structure/bed/pillow_tiny/pillow_pile = new(get_turf(src)) @@ -330,6 +327,7 @@ pillow_pile.update_icon_state() pillow_pile.update_icon() qdel(src) + return CLICK_ACTION_SUCCESS //Upgrading pillow pile to a PILLOW PILE! /obj/structure/chair/pillow_small/attackby(obj/item/used_item, mob/living/user, params) @@ -437,7 +435,7 @@ icon_state = "[base_icon_state]_[current_color]" //Removing pillow from a pile -/obj/structure/bed/pillow_large/AltClick(mob/user) +/obj/structure/bed/pillow_large/click_alt(mob/user) to_chat(user, span_notice("You take [src] from the pile.")) var/obj/item/fancy_pillow/taken_pillow = new() var/obj/structure/chair/pillow_small/pillow_pile = new(get_turf(src)) @@ -464,3 +462,4 @@ pillow_pile.update_icon_state() pillow_pile.update_icon() qdel(src) + return CLICK_ACTION_SUCCESS diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/shibari_stand.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/shibari_stand.dm index 968b6a34925..9ceeaf04bc6 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/shibari_stand.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_structures/shibari_stand.dm @@ -7,7 +7,6 @@ layer = 4 item_chair = null buildstacktype = null - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION ///Overlays for ropes var/static/mutable_appearance/shibari_rope_overlay var/static/mutable_appearance/shibari_rope_overlay_behind @@ -45,6 +44,10 @@ if(!has_buckled_mobs() && can_buckle) . += span_notice("They need to be wearing full-body shibari, and you need to be holding ropes!") +// previously NO_DECONSTRUCT +/obj/structure/chair/shibari_stand/wrench_act_secondary(mob/living/user, obj/item/weapon) + return NONE + /obj/structure/chair/shibari_stand/user_unbuckle_mob(mob/living/buckled_mob, mob/living/user) var/mob/living/buckled = buckled_mob if(buckled) diff --git a/modular_skyrat/modules/modular_weapons/code/gunsets.dm b/modular_skyrat/modules/modular_weapons/code/gunsets.dm index 7373e0fa729..09b523f2c86 100644 --- a/modular_skyrat/modules/modular_weapons/code/gunsets.dm +++ b/modular_skyrat/modules/modular_weapons/code/gunsets.dm @@ -30,10 +30,10 @@ else icon_state = initial(icon_state) -/obj/item/storage/toolbox/guncase/skyrat/AltClick(mob/user) - . = ..() +/obj/item/storage/toolbox/guncase/skyrat/click_alt(mob/user) opened = !opened update_icon() + return CLICK_ACTION_SUCCESS /obj/item/storage/toolbox/guncase/skyrat/attack_self(mob/user) . = ..() 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 d631246666c..01eda1e746d 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 @@ -171,11 +171,9 @@ update_positioning() -/obj/machinery/mounted_machine_gun/AltClick(mob/user) - . = ..() - if(!can_interact(user)) - return +/obj/machinery/mounted_machine_gun/click_alt(mob/user) toggle_cover(user) + return CLICK_ACTION_SUCCESS /obj/machinery/mounted_machine_gun/attack_hand_secondary(mob/living/user, list/modifiers) . = ..() diff --git a/modular_skyrat/modules/mutants/code/mutant_cure.dm b/modular_skyrat/modules/mutants/code/mutant_cure.dm index 5bdff67d152..59fdca63325 100644 --- a/modular_skyrat/modules/mutants/code/mutant_cure.dm +++ b/modular_skyrat/modules/mutants/code/mutant_cure.dm @@ -219,8 +219,6 @@ if(machine_stat & (NOPOWER|BROKEN|MAINT)) return - usr.set_machine(src) - var/operation = href_list["function"] var/obj/item/process = locate(href_list["item"]) in src @@ -230,7 +228,7 @@ else if(operation == "eject") ejectItem() else if(operation == "refresh") - updateUsrDialog() + SStgui.update_uis(src) else if(status != STATUS_IDLE) to_chat(usr, span_warning("[src] is currently recombinating!")) @@ -246,7 +244,7 @@ recombinate_start() use_energy(3000 JOULES) - updateUsrDialog() + SStgui.update_uis(src) /obj/machinery/rnd/rna_recombinator/proc/ejectItem() if(loaded_item) diff --git a/modular_skyrat/modules/new_cells/code/power_cell.dm b/modular_skyrat/modules/new_cells/code/power_cell.dm index d9769c479c1..7c604393386 100644 --- a/modular_skyrat/modules/new_cells/code/power_cell.dm +++ b/modular_skyrat/modules/new_cells/code/power_cell.dm @@ -4,11 +4,11 @@ icon = 'modular_skyrat/modules/new_cells/icons/power.dmi' icon_state = "crankcell" /// how much each crank will give the cell charge - var/crank_amount = 100 + var/crank_amount = STANDARD_CELL_CHARGE * 0.1 /// how fast it takes to crank to get the crank_amount var/crank_speed = 1 SECONDS /// how much gets discharged every process - var/discharge_amount = 10 + var/discharge_amount = STANDARD_CELL_CHARGE * 0.01 charge_light_type = "old" /obj/item/stock_parts/cell/crank/examine(mob/user) @@ -38,10 +38,10 @@ desc = "A special cell that will recharge itself over time." icon = 'modular_skyrat/modules/new_cells/icons/power.dmi' icon_state = "chargecell" - maxcharge = 2500 + maxcharge = STANDARD_CELL_CHARGE * 2.5 charge_light_type = "old" /// how much is recharged every process - var/recharge_amount = 200 + var/recharge_amount = STANDARD_CELL_CHARGE * 0.2 /obj/item/stock_parts/cell/self_charge/Initialize(mapload, override_maxcharge) . = ..() diff --git a/modular_skyrat/modules/oneclickantag/code/oneclickantag.dm b/modular_skyrat/modules/oneclickantag/code/oneclickantag.dm index cfe5386f4a9..bae6bea585a 100644 --- a/modular_skyrat/modules/oneclickantag/code/oneclickantag.dm +++ b/modular_skyrat/modules/oneclickantag/code/oneclickantag.dm @@ -36,14 +36,8 @@ return FALSE return TRUE -/client/proc/one_click_antag() - set name = "Create Antagonist" - set desc = "Auto-create an antagonist of your choice" - set category = "Admin.Events" - - if(holder) - holder.one_click_antag() - return +ADMIN_VERB(one_click_antag, R_ADMIN, "Create Antagonist", "Auto-create an antagonist of your choice", ADMIN_CATEGORY_EVENTS) + user.holder?.one_click_antag() /** If anyone can figure out how to get Obsessed to work I would be very appreciative. diff --git a/modular_skyrat/modules/opposing_force/code/admin_procs.dm b/modular_skyrat/modules/opposing_force/code/admin_procs.dm index 379a1de08cb..9ce7da7c459 100644 --- a/modular_skyrat/modules/opposing_force/code/admin_procs.dm +++ b/modular_skyrat/modules/opposing_force/code/admin_procs.dm @@ -1,19 +1,16 @@ -/client/proc/request_more_opfor() - set category = "Admin.Fun" - set name = "Request OPFOR" - set desc = "Request players sign up for opfor if they have antag on." - +ADMIN_VERB(request_more_opfor, R_FUN, "Request OPFOR", "Request players sign up for opfor if they have antag on.", ADMIN_CATEGORY_FUN) var/asked = 0 for(var/mob/living/carbon/human/human in GLOB.alive_player_list) if(human.client?.prefs?.read_preference(/datum/preference/toggle/be_antag)) to_chat(human, examine_block(span_greentext("The admins are looking for OPFOR players, if you're interested, sign up in the OOC tab!"))) asked++ - message_admins("[ADMIN_LOOKUP(usr)] has requested more OPFOR players! (Asked: [asked] players)") + message_admins("[ADMIN_LOOKUP(user)] has requested more OPFOR players! (Asked: [asked] players)") +ADMIN_VERB(view_opfors, R_ADMIN, "View OPFORs", "View OPFORs.", ADMIN_CATEGORY_GAME) + user.mob.client?.view_opfors() + /client/proc/view_opfors() - set name = "View OPFORs" - set category = "Admin.Game" if(holder) var/list/dat = list("") dat += SSopposing_force.get_check_antag_listing() diff --git a/modular_skyrat/modules/panicbunker/code/panicbunker.dm b/modular_skyrat/modules/panicbunker/code/panicbunker.dm index 1054fdfa851..eb9275f8855 100644 --- a/modular_skyrat/modules/panicbunker/code/panicbunker.dm +++ b/modular_skyrat/modules/panicbunker/code/panicbunker.dm @@ -1,9 +1,6 @@ GLOBAL_LIST_EMPTY(bunker_passthrough) -/client/proc/addbunkerbypass(ckeytobypass as text) - set category = "Admin" - set name = "Add PB Bypass" - set desc = "Allows a given ckey to connect despite the panic bunker for a given round." +ADMIN_VERB(addbunkerbypass, R_ADMIN, "Add PB Bypass", "Allows a given ckey to connect despite the panic bunker for a given round.", ADMIN_CATEGORY_MAIN, ckeytobypass as text|null) if(!CONFIG_GET(flag/sql_enabled)) to_chat(usr, span_adminnotice("The Database is not enabled!")) return @@ -14,11 +11,7 @@ GLOBAL_LIST_EMPTY(bunker_passthrough) log_admin("[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.") message_admins("[key_name_admin(usr)] has added [ckeytobypass] to the current round's bunker bypass list.") -/client/proc/revokebunkerbypass(ckeytobypass as text) - set category = "Admin" - set name = "Revoke PB Bypass" - set desc = "Revoke's a ckey's permission to bypass the panic bunker for a given round." - +ADMIN_VERB(revokebunkerbypass, R_ADMIN, "Revoke PB Bypass", "Revoke's a ckey's permission to bypass the panic bunker for a given round.", ADMIN_CATEGORY_MAIN, ckeytobypass as text|null) if(!CONFIG_GET(flag/sql_enabled)) to_chat(usr, span_adminnotice("The Database is not enabled!")) return diff --git a/modular_skyrat/modules/pollution/code/admin_spawn_pollution.dm b/modular_skyrat/modules/pollution/code/admin_spawn_pollution.dm index 12102f43f39..125a9fb740b 100644 --- a/modular_skyrat/modules/pollution/code/admin_spawn_pollution.dm +++ b/modular_skyrat/modules/pollution/code/admin_spawn_pollution.dm @@ -1,16 +1,12 @@ -/client/proc/spawn_pollution() - set category = "Admin.Fun" - set name = "Spawn Pollution" - set desc = "Spawns an amount of chosen pollutant at your current location." - +ADMIN_VERB(spawn_pollution, R_ADMIN, "Spawn Pollution", "Spawns an amount of chosen pollutant at your current location.", ADMIN_CATEGORY_FUN) var/list/singleton_list = SSpollution.singletons - var/choice = tgui_input_list(usr, "What type of pollutant would you like to spawn?", "Spawn Pollution", singleton_list) + var/choice = tgui_input_list(user, "What type of pollutant would you like to spawn?", "Spawn Pollution", singleton_list) if(!choice) return var/amount_choice = input("Amount of pollution:") as null|num if(!amount_choice) return - var/turf/epicenter = get_turf(mob) + var/turf/epicenter = get_turf(user.mob) epicenter.pollute_turf(choice, amount_choice) - message_admins("[ADMIN_LOOKUPFLW(usr)] spawned pollution at [epicenter.loc] ([choice] - [amount_choice]).") - log_admin("[key_name(usr)] spawned pollution at [epicenter.loc] ([choice] - [amount_choice]).") + message_admins("[ADMIN_LOOKUPFLW(user)] spawned pollution at [epicenter.loc] ([choice] - [amount_choice]).") + log_admin("[key_name(user)] spawned pollution at [epicenter.loc] ([choice] - [amount_choice]).") diff --git a/modular_skyrat/modules/pollution/code/perfumes.dm b/modular_skyrat/modules/pollution/code/perfumes.dm index 2f07404ae76..80ccf1c253e 100644 --- a/modular_skyrat/modules/pollution/code/perfumes.dm +++ b/modular_skyrat/modules/pollution/code/perfumes.dm @@ -34,8 +34,9 @@ if(has_cap) . += span_notice("Alt-click [src] to [ cap ? "take the cap off" : "put the cap on"].") -/obj/item/perfume/AltClick(mob/user) +/obj/item/perfume/click_alt(mob/user) toggle_cap(user) + return CLICK_ACTION_SUCCESS /obj/item/perfume/attack_self(mob/user, modifiers) toggle_cap(user) diff --git a/modular_skyrat/modules/primitive_cooking_additions/code/big_mortar.dm b/modular_skyrat/modules/primitive_cooking_additions/code/big_mortar.dm index 4860aed6331..282369b1e85 100644 --- a/modular_skyrat/modules/primitive_cooking_additions/code/big_mortar.dm +++ b/modular_skyrat/modules/primitive_cooking_additions/code/big_mortar.dm @@ -33,13 +33,14 @@ drop_everything_contained() return ..() -/obj/structure/large_mortar/AltClick(mob/user) +/obj/structure/large_mortar/click_alt(mob/user) if(!length(contents)) balloon_alert(user, "nothing inside") - return + return CLICK_ACTION_BLOCKING drop_everything_contained() balloon_alert(user, "removed all items") + return CLICK_ACTION_SUCCESS /// Drops all contents at the mortar /obj/structure/large_mortar/proc/drop_everything_contained() diff --git a/modular_skyrat/modules/primitive_cooking_additions/code/cutting_board.dm b/modular_skyrat/modules/primitive_cooking_additions/code/cutting_board.dm index a71e4c7d35a..e677a617817 100644 --- a/modular_skyrat/modules/primitive_cooking_additions/code/cutting_board.dm +++ b/modular_skyrat/modules/primitive_cooking_additions/code/cutting_board.dm @@ -57,13 +57,14 @@ drop_everything_contained() return ..() -/obj/item/cutting_board/AltClick(mob/user) +/obj/item/cutting_board/click_alt(mob/user) if(!length(contents)) balloon_alert(user, "nothing on board") - return + return CLICK_ACTION_BLOCKING drop_everything_contained() balloon_alert(user, "cleared board") + return CLICK_ACTION_SUCCESS ///Drops all contents at the turf of the item /obj/item/cutting_board/proc/drop_everything_contained() diff --git a/modular_skyrat/modules/primitive_cooking_additions/code/millstone.dm b/modular_skyrat/modules/primitive_cooking_additions/code/millstone.dm index 57b5d23e385..76a21851856 100644 --- a/modular_skyrat/modules/primitive_cooking_additions/code/millstone.dm +++ b/modular_skyrat/modules/primitive_cooking_additions/code/millstone.dm @@ -51,13 +51,14 @@ transfer_fingerprints_to(stone) return ..() -/obj/structure/millstone/AltClick(mob/user) +/obj/structure/millstone/click_alt(mob/user) if(!length(contents)) - balloon_alert(user, "nothing inside") - return + balloon_alert(user, "nothing inside!") + return CLICK_ACTION_BLOCKING drop_everything_contained() balloon_alert(user, "removed all items") + return CLICK_ACTION_SUCCESS /obj/structure/millstone/CtrlShiftClick(mob/user) set_anchored(!anchored) diff --git a/modular_skyrat/modules/primitive_cooking_additions/code/stone_oven.dm b/modular_skyrat/modules/primitive_cooking_additions/code/stone_oven.dm index c4c21967a3c..8ccd6e5c668 100644 --- a/modular_skyrat/modules/primitive_cooking_additions/code/stone_oven.dm +++ b/modular_skyrat/modules/primitive_cooking_additions/code/stone_oven.dm @@ -6,7 +6,6 @@ icon = 'modular_skyrat/modules/primitive_cooking_additions/icons/stone_kitchen_machines.dmi' circuit = null use_power = FALSE - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION /// A list of the different oven trays we can spawn with var/static/list/random_oven_tray_types = list( @@ -32,6 +31,16 @@ . += span_notice("It can be taken apart with a crowbar.") +// previously NO_DECONSTRUCTION +/obj/machinery/oven/stone/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) + return NONE + +/obj/machinery/oven/stone/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct) + return NONE + +/obj/machinery/oven/stone/default_pry_open(obj/item/crowbar, close_after_pry, open_density, closed_density) + return NONE + /obj/machinery/oven/stone/add_tray_to_oven(obj/item/plate/oven_tray, mob/baker) used_tray = oven_tray diff --git a/modular_skyrat/modules/primitive_cooking_additions/code/stone_stove.dm b/modular_skyrat/modules/primitive_cooking_additions/code/stone_stove.dm index 0057e758571..cdfd64719e3 100644 --- a/modular_skyrat/modules/primitive_cooking_additions/code/stone_stove.dm +++ b/modular_skyrat/modules/primitive_cooking_additions/code/stone_stove.dm @@ -10,7 +10,6 @@ use_power = FALSE circuit = null resistance_flags = FIRE_PROOF - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION /obj/machinery/primitive_stove/Initialize(mapload) . = ..() @@ -22,6 +21,13 @@ . += span_notice("It can be taken apart with a crowbar.") +// previously NO_DECONSTRUCTION +/obj/machinery/primitive_stove/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) + return NONE + +/obj/machinery/primitive_stove/default_deconstruction_crowbar(obj/item/crowbar, ignore_panel, custom_deconstruct) + return NONE + /obj/machinery/primitive_stove/crowbar_act(mob/living/user, obj/item/tool) user.balloon_alert_to_viewers("disassembling...") if(!tool.use_tool(src, user, 2 SECONDS, volume = 100)) diff --git a/modular_skyrat/modules/primitive_production/code/glassblowing.dm b/modular_skyrat/modules/primitive_production/code/glassblowing.dm index ed7b4a31ff8..59198aa1112 100644 --- a/modular_skyrat/modules/primitive_production/code/glassblowing.dm +++ b/modular_skyrat/modules/primitive_production/code/glassblowing.dm @@ -227,7 +227,6 @@ if(!Adjacent(usr)) return add_fingerprint(usr) - usr.set_machine(src) var/obj/item/glassblowing/molten_glass/glass = glass_ref?.resolve() var/actioning_speed = usr.mind.get_skill_modifier(/datum/skill/production, SKILL_SPEED_MODIFIER) * DEFAULT_TIMED diff --git a/modular_skyrat/modules/primitive_structures/code/fencing.dm b/modular_skyrat/modules/primitive_structures/code/fencing.dm index 0aeb5a71e20..20816e9ba55 100644 --- a/modular_skyrat/modules/primitive_structures/code/fencing.dm +++ b/modular_skyrat/modules/primitive_structures/code/fencing.dm @@ -7,7 +7,7 @@ icon_state = "fence" layer = BELOW_OBJ_LAYER // I think this is the default but lets be safe? resistance_flags = FLAMMABLE - flags_1 = NO_DECONSTRUCTION | ON_BORDER_1 + flags_1 = ON_BORDER_1 /// If we randomize our icon on spawning var/random_icons = TRUE @@ -22,6 +22,10 @@ ) update_appearance() +// previously NO_DECONSTRUCTION +/obj/structure/railing/wirecutter_act(mob/living/user, obj/item/I) + return NONE + // Fence gates for the above mentioned fences /obj/structure/railing/wooden_fencing/gate diff --git a/modular_skyrat/modules/primitive_structures/code/storage_structures.dm b/modular_skyrat/modules/primitive_structures/code/storage_structures.dm index 58c08df7941..d35bd9ce1c6 100644 --- a/modular_skyrat/modules/primitive_structures/code/storage_structures.dm +++ b/modular_skyrat/modules/primitive_structures/code/storage_structures.dm @@ -5,7 +5,6 @@ icon_state = "shelf_wood" icon = 'modular_skyrat/modules/primitive_structures/icons/storage.dmi' resistance_flags = FLAMMABLE - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION /obj/structure/rack/wooden/MouseDrop_T(obj/object, mob/user, params) . = ..() @@ -16,6 +15,9 @@ object.pixel_x = clamp(text2num(LAZYACCESS(modifiers, ICON_X)) - 16, -(world.icon_size / 3), world.icon_size / 3) object.pixel_y = text2num(LAZYACCESS(modifiers, ICON_Y)) > 16 ? 10 : -4 +/obj/structure/rack/wrench_act_secondary(mob/living/user, obj/item/tool) + return NONE + /obj/structure/rack/wooden/crowbar_act(mob/living/user, obj/item/tool) user.balloon_alert_to_viewers("disassembling...") if(!tool.use_tool(src, user, 2 SECONDS, volume = 100)) @@ -37,28 +39,18 @@ base_icon_state = "barrel" icon = 'modular_skyrat/modules/primitive_structures/icons/storage.dmi' resistance_flags = FLAMMABLE - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION + material_drop = /obj/item/stack/sheet/mineral/wood + material_drop_amount = 4 + cutting_tool = /obj/item/crowbar -/obj/structure/closet/crate/wooden/storage_barrel/crowbar_act(mob/living/user, obj/item/tool) - user.balloon_alert_to_viewers("disassembling...") - if(!tool.use_tool(src, user, 2 SECONDS, volume = 100)) - return - new /obj/item/stack/sheet/mineral/clay(drop_location(), 5) - deconstruct(TRUE) - return ITEM_INTERACT_SUCCESS - -/obj/structure/closet/crate/wooden/storage_barrel/atom_deconstruct(disassembled = TRUE) - new /obj/item/stack/sheet/mineral/wood(drop_location(), 4) - return ..() - -/obj/machinery/smartfridge/producebin - name = "Produce Bin" - desc = "A wooden hamper, used to hold plant products and try keep them safe from pests." - icon_state = "producebin" +/obj/machinery/smartfridge/wooden + name = "Debug Wooden Smartfridge" + desc = "You shouldn't be seeing this!" icon = 'modular_skyrat/modules/primitive_structures/icons/storage.dmi' + icon_state = "producebin" resistance_flags = FLAMMABLE - base_build_path = /obj/machinery/smartfridge/producebin - base_icon_state = "produce" + base_build_path = /obj/machinery/smartfridge/wooden + base_icon_state = "producebin" use_power = NO_POWER_USE light_power = 0 idle_power_usage = 0 @@ -67,14 +59,16 @@ can_atmos_pass = ATMOS_PASS_YES visible_contents = TRUE -/obj/machinery/smartfridge/producebin/accept_check(obj/item/weapon) - return (istype(weapon, /obj/item/food/grown)) +/obj/machinery/smartfridge/wooden/Initialize(mapload) + . = ..() + if(type == /obj/machinery/smartfridge/wooden) // don't even let these prototypes exist + return INITIALIZE_HINT_QDEL -/obj/machinery/smartfridge/producebin/structure_examine() - . = span_info("The whole rack can be [EXAMINE_HINT("pried")] apart.") +// previously NO_DECONSTRUCTION +/obj/machinery/smartfridge/wooden/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) + return NONE - -/obj/machinery/smartfridge/producebin/crowbar_act(mob/living/user, obj/item/tool) +/obj/machinery/smartfridge/wooden/crowbar_act(mob/living/user, obj/item/tool) user.balloon_alert_to_viewers("disassembling...") if(!tool.use_tool(src, user, 2 SECONDS, volume = 100)) return @@ -82,92 +76,51 @@ deconstruct(TRUE) return ITEM_INTERACT_SUCCESS -/obj/machinery/smartfridge/seedshelf +/obj/machinery/smartfridge/wooden/structure_examine() + . = span_info("The whole rack can be [EXAMINE_HINT("pried")] apart.") + +/obj/machinery/smartfridge/wooden/produce_bin + name = "produce bin" + desc = "A wooden hamper, used to hold plant products and try to keep them safe from pests." + icon_state = "producebin" + base_build_path = /obj/machinery/smartfridge/wooden/produce_bin + base_icon_state = "producebin" + +/obj/machinery/smartfridge/wooden/produce_bin/accept_check(obj/item/item_to_check) + var/static/list/accepted_items = list( + /obj/item/food/grown, + /obj/item/grown, + /obj/item/graft, + ) + + return is_type_in_list(item_to_check, accepted_items) + +/obj/machinery/smartfridge/wooden/seed_shelf name = "Seedshelf" desc = "A wooden shelf, used to hold seeds preventing them from germinating early." icon_state = "seedshelf" - icon = 'modular_skyrat/modules/primitive_structures/icons/storage.dmi' - resistance_flags = FLAMMABLE - base_build_path = /obj/machinery/smartfridge/seedshelf + base_build_path = /obj/machinery/smartfridge/wooden/seed_shelf base_icon_state = "seed" - use_power = NO_POWER_USE - light_power = 0 - idle_power_usage = 0 - circuit = null - has_emissive = FALSE - can_atmos_pass = ATMOS_PASS_YES - visible_contents = TRUE -/obj/machinery/smartfridge/seedshelf/accept_check(obj/item/weapon) +/obj/machinery/smartfridge/wooden/seedshelf/wooden/accept_check(obj/item/weapon) return istype(weapon, /obj/item/seeds) -/obj/machinery/smartfridge/seedshelf/structure_examine() - . = span_info("The whole rack can be [EXAMINE_HINT("pried")] apart.") - -/obj/machinery/smartfridge/seedshelf/crowbar_act(mob/living/user, obj/item/tool) - user.balloon_alert_to_viewers("disassembling...") - if(!tool.use_tool(src, user, 2 SECONDS, volume = 100)) - return - new /obj/item/stack/sheet/mineral/wood(drop_location(), 10) - deconstruct(TRUE) - return ITEM_INTERACT_SUCCESS - -/obj/machinery/smartfridge/rationshelf +/obj/machinery/smartfridge/wooden/ration_shelf name = "Ration shelf" desc = "A wooden shelf, used to store food... preferably preserved." icon_state = "rationshelf" - icon = 'modular_skyrat/modules/primitive_structures/icons/storage.dmi' - resistance_flags = FLAMMABLE - base_build_path = /obj/machinery/smartfridge/rationshelf + base_build_path = /obj/machinery/smartfridge/wooden/ration_shelf base_icon_state = "ration" - use_power = NO_POWER_USE - light_power = 0 - idle_power_usage = 0 - circuit = null - has_emissive = FALSE - can_atmos_pass = ATMOS_PASS_YES - visible_contents = TRUE -/obj/machinery/smartfridge/rationshelf/accept_check(obj/item/weapon) +/obj/machinery/smartfridge/wooden/rationshelf/wooden/accept_check(obj/item/weapon) return (IS_EDIBLE(weapon) || (istype(weapon,/obj/item/reagent_containers/cup/bowl) && length(weapon.reagents?.reagent_list))) -/obj/machinery/smartfridge/rationshelf/structure_examine() - . = span_info("The whole rack can be [EXAMINE_HINT("pried")] apart.") - -/obj/machinery/smartfridge/rationshelf/crowbar_act(mob/living/user, obj/item/tool) - user.balloon_alert_to_viewers("disassembling...") - if(!tool.use_tool(src, user, 2 SECONDS, volume = 100)) - return - new /obj/item/stack/sheet/mineral/wood(drop_location(), 10) - deconstruct(TRUE) - return ITEM_INTERACT_SUCCESS - -/obj/machinery/smartfridge/producedisplay +/obj/machinery/smartfridge/wooden/produce_display name = "Produce display" desc = "A wooden table with awning, used to display produce items." icon_state = "producedisplay" - icon = 'modular_skyrat/modules/primitive_structures/icons/storage.dmi' - resistance_flags = FLAMMABLE - base_build_path = /obj/machinery/smartfridge/producedisplay + base_build_path = /obj/machinery/smartfridge/wooden/produce_display base_icon_state = "nonfood" - use_power = NO_POWER_USE - light_power = 0 - idle_power_usage = 0 - circuit = null - has_emissive = FALSE - can_atmos_pass = ATMOS_PASS_YES - visible_contents = TRUE -/obj/machinery/smartfridge/producedisplay/accept_check(obj/item/weapon) +/obj/machinery/smartfridge/wooden/producedisplay/accept_check(obj/item/weapon) return (istype(weapon, /obj/item/grown) || istype(weapon, /obj/item/bouquet) || istype(weapon, /obj/item/clothing/head/costume/garland)) - -/obj/machinery/smartfridge/producedisplay/structure_examine() - . = span_info("The whole rack can be [EXAMINE_HINT("pried")] apart.") - -/obj/machinery/smartfridge/producedisplay/crowbar_act(mob/living/user, obj/item/tool) - user.balloon_alert_to_viewers("disassembling...") - if(!tool.use_tool(src, user, 2 SECONDS, volume = 100)) - return - new /obj/item/stack/sheet/mineral/wood(drop_location(), 10) - deconstruct(TRUE) - return ITEM_INTERACT_SUCCESS diff --git a/modular_skyrat/modules/primitive_structures/code/windows.dm b/modular_skyrat/modules/primitive_structures/code/windows.dm index ec861bb2d12..c2c27c62306 100644 --- a/modular_skyrat/modules/primitive_structures/code/windows.dm +++ b/modular_skyrat/modules/primitive_structures/code/windows.dm @@ -4,7 +4,7 @@ icon = 'modular_skyrat/modules/primitive_structures/icons/windows.dmi' icon_state = "green_glass" flags_1 = NONE - obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION + obj_flags = parent_type::obj_flags | NO_DEBRIS_AFTER_DECONSTRUCTION can_be_unanchored = FALSE fulltile = TRUE flags_1 = PREVENT_CLICK_UNDER_1 diff --git a/modular_skyrat/modules/salon/code/hair_tie.dm b/modular_skyrat/modules/salon/code/hair_tie.dm index 2b490ec749b..73b1a28d93b 100644 --- a/modular_skyrat/modules/salon/code/hair_tie.dm +++ b/modular_skyrat/modules/salon/code/hair_tie.dm @@ -86,16 +86,16 @@ user.set_hairstyle(actual_hairstyle, update = TRUE) actual_hairstyle = null -/obj/item/clothing/head/hair_tie/AltClick(mob/living/user) - . = ..() +/obj/item/clothing/head/hair_tie/click_alt(mob/living/user) if(!(user.get_slot_by_item(src) == ITEM_SLOT_HANDS)) balloon_alert(user, "hold in-hand!") - return + return CLICK_ACTION_BLOCKING user.visible_message( span_danger("[user.name] puts [src] around [user.p_their()] fingers, beginning to flick it!"), span_notice("You try to flick [src]!"), ) flick_hair_tie(user) + return CLICK_ACTION_SUCCESS ///This proc flicks the hair tie out of the player's hand, tripping the target hit for 1 second /obj/item/clothing/head/hair_tie/proc/flick_hair_tie(mob/living/user) @@ -143,7 +143,7 @@ ) build_path = /obj/item/clothing/head/hair_tie/plastic_beads category = list( - RND_CATEGORY_INITIAL, + RND_CATEGORY_INITIAL, RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_SERVICE, ) departmental_flags = DEPARTMENT_BITFLAG_SERVICE 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 e3b61e0f3e2..fb54222abdb 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 @@ -80,15 +80,15 @@ . = ..() . += span_notice("ALT-Click to turn ON when closed.") -/obj/machinery/self_actualization_device/AltClick(mob/user) - . = ..() +/obj/machinery/self_actualization_device/click_alt(mob/user) if(!powered() || !occupant || state_open) - return FALSE + return CLICK_ACTION_BLOCKING to_chat(user, "You power on [src].") addtimer(CALLBACK(src, PROC_REF(eject_new_you)), processing_time, TIMER_OVERRIDE|TIMER_UNIQUE) processing = TRUE update_appearance() + return CLICK_ACTION_SUCCESS /obj/machinery/self_actualization_device/container_resist_act(mob/living/user) if(state_open) diff --git a/modular_skyrat/modules/server_overflow/code/chat_link.dm b/modular_skyrat/modules/server_overflow/code/chat_link.dm index 843ec276ac5..85489d1dbe1 100644 --- a/modular_skyrat/modules/server_overflow/code/chat_link.dm +++ b/modular_skyrat/modules/server_overflow/code/chat_link.dm @@ -60,19 +60,15 @@ html = msg, confidential = TRUE) -/client/proc/request_help() - set category = "Admin" - set name = "Cross-server Help Request" - set desc = "Sends a loud message to all other servers that we are crosslinked to!" - - var/help_request_message = tgui_input_text(src, "Input help message!", "Help message", "Send help!", 150, FALSE) +ADMIN_VERB(request_help, R_ADMIN, "Cross-server Help Request", "Sends a loud message to all other servers that we are crosslinked to!", ADMIN_CATEGORY_MAIN) + var/help_request_message = tgui_input_text(user, "Input help message!", "Help message", "Send help!", 150, FALSE) if(!help_request_message) return - send2adminchat(ckey, "CROSSLINK HELP REQUEST([CONFIG_GET(string/cross_server_name) ? CONFIG_GET(string/cross_server_name) : station_name()]): [help_request_message]") - send_help_request_to_other_server(ckey, help_request_message) + send2adminchat(user.ckey, "CROSSLINK HELP REQUEST([CONFIG_GET(string/cross_server_name) ? CONFIG_GET(string/cross_server_name) : station_name()]): [help_request_message]") + send_help_request_to_other_server(user.ckey, help_request_message) - message_admins("[ADMIN_LOOKUPFLW(usr)] sent out a cross-server help request with the message: [help_request_message].") - log_admin("[key_name(usr)] sent cross-server help request [help_request_message].") + message_admins("[ADMIN_LOOKUPFLW(user)] sent out a cross-server help request with the message: [help_request_message].") + log_admin("[key_name(user)] sent cross-server help request [help_request_message].") // Oh no, they need help! /proc/send_help_request_to_other_server(exp_name, message) diff --git a/modular_skyrat/modules/specialist_armor/code/sacrificial.dm b/modular_skyrat/modules/specialist_armor/code/sacrificial.dm index 45643140f83..71bbf99db4d 100644 --- a/modular_skyrat/modules/specialist_armor/code/sacrificial.dm +++ b/modular_skyrat/modules/specialist_armor/code/sacrificial.dm @@ -79,8 +79,9 @@ QDEL_NULL(face_shield) return ..() -/obj/item/clothing/head/helmet/sf_sacrificial/AltClick(mob/user) +/obj/item/clothing/head/helmet/sf_sacrificial/click_alt(mob/user) remove_face_shield(user) + return CLICK_ACTION_SUCCESS /// Attached the passed face shield to the helmet. /obj/item/clothing/head/helmet/sf_sacrificial/proc/add_face_shield(mob/living/carbon/human/user, obj/shield_in_question) diff --git a/modular_skyrat/modules/stasisrework/code/stasissleeper.dm b/modular_skyrat/modules/stasisrework/code/stasissleeper.dm index be21887eed6..abb7437d6f6 100644 --- a/modular_skyrat/modules/stasisrework/code/stasissleeper.dm +++ b/modular_skyrat/modules/stasisrework/code/stasissleeper.dm @@ -13,6 +13,7 @@ var/last_stasis_sound = FALSE fair_market_price = 10 payment_department = ACCOUNT_MED + interaction_flags_click = ALLOW_SILICON_REACH /obj/machinery/stasissleeper/Destroy() . = ..() @@ -53,9 +54,7 @@ playsound(src, 'sound/machines/synth_no.ogg', 50, TRUE, frequency = sound_freq) last_stasis_sound = _running -/obj/machinery/stasissleeper/AltClick(mob/user) - if(!user.can_perform_action(src, ALLOW_SILICON_REACH)) - return +/obj/machinery/stasissleeper/click_alt(mob/user) if(!panel_open) user.visible_message(span_notice("\The [src] [state_open ? "hisses as it seals shut." : "hisses as it swings open."]."), \ span_notice("You [state_open ? "close" : "open"] \the [src]."), \ @@ -65,6 +64,8 @@ else open_machine() + return CLICK_ACTION_SUCCESS + /obj/machinery/stasissleeper/Exited(atom/movable/AM, atom/newloc) if(!state_open && AM == occupant) container_resist_act(AM) @@ -141,7 +142,7 @@ /obj/machinery/stasissleeper/default_pry_open(obj/item/used_item) if(occupant) thaw_them(occupant) - . = !(state_open || panel_open || (obj_flags & NO_DECONSTRUCTION)) && used_item.tool_behaviour == TOOL_CROWBAR + . = !(state_open || panel_open) && used_item.tool_behaviour == TOOL_CROWBAR if(.) used_item.play_tool_sound(src, 50) visible_message(span_notice("[usr] pries open [src]."), span_notice("You pry open [src].")) diff --git a/modular_skyrat/modules/stone/code/stone.dm b/modular_skyrat/modules/stone/code/stone.dm index 0ae23c39c45..ac36480ac79 100644 --- a/modular_skyrat/modules/stone/code/stone.dm +++ b/modular_skyrat/modules/stone/code/stone.dm @@ -11,7 +11,6 @@ resistance_flags = FIRE_PROOF merge_type = /obj/item/stack/sheet/mineral/stone grind_results = null - point_value = 0 material_type = /datum/material/stone matter_amount = 0 source = null diff --git a/modular_skyrat/modules/synths/code/bodyparts/stomach.dm b/modular_skyrat/modules/synths/code/bodyparts/stomach.dm index 80ba4fa5223..5d14829cc92 100644 --- a/modular_skyrat/modules/synths/code/bodyparts/stomach.dm +++ b/modular_skyrat/modules/synths/code/bodyparts/stomach.dm @@ -56,11 +56,13 @@ UnregisterSignal(stomach_owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT) ///Handles charging the synth from borg chargers -/obj/item/organ/internal/stomach/synth/proc/on_borg_charge(datum/source, amount) +/obj/item/organ/internal/stomach/synth/proc/on_borg_charge(datum/source, datum/callback/charge_cell, seconds_per_tick) SIGNAL_HANDLER if(owner.nutrition >= NUTRITION_LEVEL_ALMOST_FULL) return - amount /= 50 // Lowers the charging amount so it isn't instant - owner.nutrition = min((owner.nutrition + amount), NUTRITION_LEVEL_ALMOST_FULL) // Makes sure we don't make the synth too full, which would apply the overweight slowdown + // I am NOT rewriting this to fit with TG's standard. I have like 70 bugfixes waiting. Feel free to give synths actual cells if I don't i the future + // ~Waterpig + + owner.nutrition = min(owner.nutrition + (40 / seconds_per_tick), NUTRITION_LEVEL_ALMOST_FULL) // Makes sure we don't make the synth too full, which would apply the overweight slowdown diff --git a/modular_skyrat/modules/tarkon/code/misc-fluff/fluff.dm b/modular_skyrat/modules/tarkon/code/misc-fluff/fluff.dm index f72fc0a99d3..cf7c4bd7005 100644 --- a/modular_skyrat/modules/tarkon/code/misc-fluff/fluff.dm +++ b/modular_skyrat/modules/tarkon/code/misc-fluff/fluff.dm @@ -123,6 +123,6 @@ name = "paper - 'Command Safe Note'" default_raw_text = "Heh... I couldn't handle letting those older papers go, something about them reminded me about why I jumped on this job. The \"Safety of the future\" spiels... Now? Any dingbat can buy their own little constructor in a box... Fancy that we got one ourself, Thing has some handy designs..

    Well- That asside, we did get some new updated circuit boards. Industry standard gave us two sets of research constructor boards for redundancy, So we set the spare set in the special safe within the comms room." -/obj/item/areaeditor/blueprints/tarkon +/obj/item/blueprints/tarkon desc = "Blueprints of the Tarkon surface breaching drill and several Tarkon base designs. Red, stamped text reads \"Confidential\" on the backside of it." name = "Tarkon Design Prints" diff --git a/modular_skyrat/modules/time_clock/code/console.dm b/modular_skyrat/modules/time_clock/code/console.dm index 2d4891366a1..8b399d94dec 100644 --- a/modular_skyrat/modules/time_clock/code/console.dm +++ b/modular_skyrat/modules/time_clock/code/console.dm @@ -77,14 +77,11 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/time_clock, 28) playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) return TRUE -/obj/machinery/time_clock/AltClick(mob/user) - . = ..() - if(!Adjacent(user)) - to_chat(user, span_warning("You are out of range of the [src]!")) - return FALSE - +/obj/machinery/time_clock/click_alt(mob/user) if(!eject_inserted_id(user)) - return FALSE + return CLICK_ACTION_BLOCKING + + return CLICK_ACTION_SUCCESS ///Ejects the ID stored inside of the parent machine, if there is one. /obj/machinery/time_clock/proc/eject_inserted_id(mob/recepient) diff --git a/modular_skyrat/modules/time_clock/code/console_tgui.dm b/modular_skyrat/modules/time_clock/code/console_tgui.dm index 64b576828d0..4101ea05932 100644 --- a/modular_skyrat/modules/time_clock/code/console_tgui.dm +++ b/modular_skyrat/modules/time_clock/code/console_tgui.dm @@ -20,7 +20,7 @@ /obj/item/circuitboard/machine/techfab/department/medical, \ /obj/item/circuitboard/machine/techfab/department/cargo, \ /obj/item/circuitboard/machine/techfab/department/science, \ - /obj/item/areaeditor/blueprints, \ + /obj/item/blueprints, \ /obj/item/pipe_dispenser/bluespace, \ /obj/item/mod/control/pre_equipped/advanced, \ /obj/item/clothing/shoes/magboots/advance, \ diff --git a/modular_skyrat/modules/title_screen/code/title_screen_controls.dm b/modular_skyrat/modules/title_screen/code/title_screen_controls.dm index 3f241af0f23..f3f550e3ffc 100644 --- a/modular_skyrat/modules/title_screen/code/title_screen_controls.dm +++ b/modular_skyrat/modules/title_screen/code/title_screen_controls.dm @@ -2,19 +2,13 @@ /** * Enables an admin to upload a new titlescreen image. */ -/client/proc/admin_change_title_screen() - set category = "Admin.Fun" - set name = "Title Screen: Change" - - if(!check_rights(R_FUN)) - return - - log_admin("[key_name(usr)] is changing the title screen.") - message_admins("[key_name_admin(usr)] is changing the title screen.") +ADMIN_VERB(admin_change_title_screen, R_FUN, "Title Screen: Change", "Upload a new titlescreen image.", ADMIN_CATEGORY_FUN) + log_admin("[key_name(user)] is changing the title screen.") + message_admins("[key_name_admin(user)] is changing the title screen.") switch(alert(usr, "Please select a new title screen.", "Title Screen", "Change", "Reset", "Cancel")) if("Change") - var/file = input(usr) as icon|null + var/file = input(user) as icon|null if(!file) return SStitle.change_title_screen(file) @@ -26,13 +20,7 @@ /** * Sets a titlescreen notice, a big red text on the main screen. */ -/client/proc/change_title_screen_notice() - set category = "Admin.Fun" - set name = "Title Screen: Set Notice" - - if(!check_rights(R_FUN)) - return - +ADMIN_VERB(change_title_screen_notice, R_FUN, "Title Screen: Set Notice", "Sets a titlescreen notice, a big red text on the main screen.", ADMIN_CATEGORY_FUN) log_admin("[key_name(usr)] is setting the title screen notice.") message_admins("[key_name_admin(usr)] is setting the title screen notice.") @@ -62,15 +50,9 @@ /** * An admin debug command that enables you to change the HTML on the go. */ -/client/proc/change_title_screen_html() - set category = "Admin.Fun" - set name = "Title Screen: Set HTML" - - if(!check_rights(R_DEBUG)) - return - - log_admin("[key_name(usr)] is setting the title screen HTML.") - message_admins("[key_name_admin(usr)] is setting the title screen HTML.") +ADMIN_VERB(change_title_screen_html, R_DEBUG, "Title Screen: Set HTML", "Change lobby screen HTML on the go.", ADMIN_CATEGORY_FUN) + log_admin("[key_name(user)] is setting the title screen HTML.") + message_admins("[key_name_admin(user)] is setting the title screen HTML.") var/new_html = input(usr, "Please enter your desired HTML(WARNING: YOU WILL BREAK SHIT)", "DANGER: TITLE HTML EDIT") as message|null @@ -80,4 +62,4 @@ SStitle.title_html = new_html SStitle.show_title_screen() - message_admins("[key_name_admin(usr)] has changed the title screen HTML.") + message_admins("[key_name_admin(user)] has changed the title screen HTML.") diff --git a/modular_skyrat/modules/turretid/code/turret_id_system.dm b/modular_skyrat/modules/turretid/code/turret_id_system.dm index bae950e5b08..4b7c5ffd170 100644 --- a/modular_skyrat/modules/turretid/code/turret_id_system.dm +++ b/modular_skyrat/modules/turretid/code/turret_id_system.dm @@ -20,7 +20,7 @@ GLOBAL_LIST_EMPTY(turret_id_refs) /obj/machinery/turretid var/system_id //The ID system for turrets, will get any turrets with the same ID and put them in controlled turrets -/obj/machinery/turretid/LateInitialize() +/obj/machinery/turretid/post_machine_initialize() . = ..() if(system_id && GLOB.turret_id_refs[system_id]) for(var/i in GLOB.turret_id_refs[system_id]) diff --git a/modular_skyrat/modules/wargame_projectors/code/projectors.dm b/modular_skyrat/modules/wargame_projectors/code/projectors.dm index 49c3d46847a..fe34b3a68af 100644 --- a/modular_skyrat/modules/wargame_projectors/code/projectors.dm +++ b/modular_skyrat/modules/wargame_projectors/code/projectors.dm @@ -86,7 +86,7 @@ /obj/item/wargame_projector/attack_self(mob/user) select_hologram(user) -/obj/item/wargame_projector/AltClick(mob/user) +/obj/item/wargame_projector/click_alt(mob/user) var/selected_color = tgui_input_list(user, "Select a color", "Color Selection", color_options) if(isnull(selected_color)) balloon_alert(user, "no color change") @@ -95,6 +95,7 @@ holosign_color = color_to_set_to balloon_alert(user, "color changed") set_greyscale(holosign_color) + return CLICK_ACTION_SUCCESS /obj/item/wargame_projector/CtrlClick(mob/user) if(tgui_alert(usr,"Clear all currently active holograms?", "Hologram Removal", list("Yes", "No")) == "Yes") diff --git a/modular_skyrat/modules/wrestlingring/code/wrestlingring.dm b/modular_skyrat/modules/wrestlingring/code/wrestlingring.dm index d865fc0653f..384921be62a 100644 --- a/modular_skyrat/modules/wrestlingring/code/wrestlingring.dm +++ b/modular_skyrat/modules/wrestlingring/code/wrestlingring.dm @@ -121,8 +121,6 @@ ///Implements behaviour that makes it possible to unanchor the railing. /obj/structure/wrestling_corner/wrench_act(mob/living/user, obj/item/tool) . = ..() - if(obj_flags & NO_DECONSTRUCTION) - return to_chat(user, span_notice("You begin to [anchored ? "unfasten the turnbuckle from":"fasten the turnbuckle to"] the floor...")) if(tool.use_tool(src, user, volume = 75, extra_checks = CALLBACK(src, PROC_REF(check_anchored), anchored))) set_anchored(!anchored) diff --git a/modular_zubbers/code/game/machinery/burger_reactor/reactor.dm b/modular_zubbers/code/game/machinery/burger_reactor/reactor.dm index 899297d7447..a655eb44f90 100644 --- a/modular_zubbers/code/game/machinery/burger_reactor/reactor.dm +++ b/modular_zubbers/code/game/machinery/burger_reactor/reactor.dm @@ -169,7 +169,7 @@ return FALSE //Remove the rod. -/obj/machinery/power/rbmk2/AltClick(mob/living/user) +/obj/machinery/power/rbmk2/click_alt(mob/living/user) if(!active && stored_rod) src.add_fingerprint(user) stored_rod.add_fingerprint(user) diff --git a/modular_zubbers/code/game/machinery/computer/orders/order_computer/cook_order_interdyne.dm b/modular_zubbers/code/game/machinery/computer/orders/order_computer/cook_order_interdyne.dm index 4aacd9cbb99..02dfbd73f41 100644 --- a/modular_zubbers/code/game/machinery/computer/orders/order_computer/cook_order_interdyne.dm +++ b/modular_zubbers/code/game/machinery/computer/orders/order_computer/cook_order_interdyne.dm @@ -24,7 +24,7 @@ /// The resolved bank account var/datum/bank_account/synced_bank_account = null -/obj/machinery/computer/order_console/cook/interdyne/LateInitialize() +/obj/machinery/computer/order_console/cook/interdyne/post_machine_initialize() . = ..() synced_bank_account = SSeconomy.get_dep_account(credits_account == "" ? ACCOUNT_CAR : credits_account) diff --git a/modular_zubbers/code/game/machinery/department_balance.dm b/modular_zubbers/code/game/machinery/department_balance.dm index 4bd5cafcf01..76e37cbb7fe 100644 --- a/modular_zubbers/code/game/machinery/department_balance.dm +++ b/modular_zubbers/code/game/machinery/department_balance.dm @@ -11,7 +11,7 @@ /// The resolved bank account var/datum/bank_account/synced_bank_account = null -/obj/machinery/status_display/department_balance/LateInitialize() +/obj/machinery/status_display/department_balance/post_machine_initialize() . = ..() start_process() diff --git a/modular_zubbers/code/game/machinery/syndiepad.dm b/modular_zubbers/code/game/machinery/syndiepad.dm index 8f9bc91d0dd..f1d8cf3be7b 100644 --- a/modular_zubbers/code/game/machinery/syndiepad.dm +++ b/modular_zubbers/code/game/machinery/syndiepad.dm @@ -69,7 +69,7 @@ /// The resolved bank account var/datum/bank_account/synced_bank_account = null -/obj/machinery/computer/piratepad_control/syndiepad/LateInitialize() +/obj/machinery/computer/piratepad_control/syndiepad/post_machine_initialize() . = ..() synced_bank_account = SSeconomy.get_dep_account(credits_account == "" ? ACCOUNT_CAR : credits_account) diff --git a/modular_zubbers/code/game/objects/items/robot/items/harm_alarm_new.dm b/modular_zubbers/code/game/objects/items/robot/items/harm_alarm_new.dm index 3c9b3767f3c..29ac3ae46e7 100644 --- a/modular_zubbers/code/game/objects/items/robot/items/harm_alarm_new.dm +++ b/modular_zubbers/code/game/objects/items/robot/items/harm_alarm_new.dm @@ -5,7 +5,7 @@ desc = "Releases a harmless blast that confuses most organics. Use in case of hostile blue whales." var/alarm_phrase = "HARM" -/obj/item/harmalarm/bubbers/AltClick(mob/living/user) +/obj/item/harmalarm/bubbers/click_alt(mob/living/user) var/str = reject_bad_text(tgui_input_text(user, "What would your alarm like to broadcast?", "Alarm Phrase", alarm_phrase, MAX_NAME_LEN)) //Limit of 42 characters. if(!str) to_chat(user, span_warning("Invalid text!")) diff --git a/modular_zubbers/code/game/objects/structures/chalkboard.dm b/modular_zubbers/code/game/objects/structures/chalkboard.dm index 6466e9779e8..586302b2ec7 100644 --- a/modular_zubbers/code/game/objects/structures/chalkboard.dm +++ b/modular_zubbers/code/game/objects/structures/chalkboard.dm @@ -54,7 +54,7 @@ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN /obj/structure/chalkboard/wrench_act_secondary(mob/living/user, obj/item/tool) - if(obj_flags & NO_DECONSTRUCTION) + if(obj_flags & NO_DEBRIS_AFTER_DECONSTRUCTION) return FALSE to_chat(user, span_notice("You start deconstructing [src]...")) if(tool.use_tool(src, user, 4 SECONDS, volume=50)) @@ -64,7 +64,7 @@ /obj/structure/chalkboard/handle_deconstruct(disassembled = TRUE) . = ..() - if(!(obj_flags & NO_DECONSTRUCTION)) + if(!(obj_flags & NO_DEBRIS_AFTER_DECONSTRUCTION)) new /obj/item/stack/sheet/mineral/wood(drop_location(), 10) qdel(src) diff --git a/modular_zubbers/code/modules/antagonists/bloodsucker/structures/coffin.dm b/modular_zubbers/code/modules/antagonists/bloodsucker/structures/coffin.dm index c25b602cdb0..e7b5b5b3cdc 100644 --- a/modular_zubbers/code/modules/antagonists/bloodsucker/structures/coffin.dm +++ b/modular_zubbers/code/modules/antagonists/bloodsucker/structures/coffin.dm @@ -302,7 +302,7 @@ return inserted /// Distance Check (Inside Of) -/obj/structure/closet/crate/coffin/AltClick(mob/user) +/obj/structure/closet/crate/coffin/click_alt(mob/user) . = ..() if(user in src) LockMe(user, !locked) diff --git a/modular_zubbers/code/modules/antagonists/bloodsucker/structures/crypt.dm b/modular_zubbers/code/modules/antagonists/bloodsucker/structures/crypt.dm index c155f45087b..d3ca07c07e8 100644 --- a/modular_zubbers/code/modules/antagonists/bloodsucker/structures/crypt.dm +++ b/modular_zubbers/code/modules/antagonists/bloodsucker/structures/crypt.dm @@ -72,7 +72,7 @@ return FALSE return TRUE -/obj/structure/bloodsucker/AltClick(mob/user) +/obj/structure/bloodsucker/click_alt(mob/user) . = ..() if(user == owner && user.Adjacent(src)) balloon_alert(user, "unbolt [src]?") diff --git a/modular_zubbers/code/modules/debug_tools/physgun.dm b/modular_zubbers/code/modules/debug_tools/physgun.dm index b9b247e1a87..3c75f9535da 100644 --- a/modular_zubbers/code/modules/debug_tools/physgun.dm +++ b/modular_zubbers/code/modules/debug_tools/physgun.dm @@ -77,7 +77,7 @@ if(handlet_atom) release_atom() -/obj/item/physic_manipulation_tool/AltClick(mob/user) +/obj/item/physic_manipulation_tool/click_alt(mob/user) . = ..() var/choised_color = input(usr, "Pick new effects color", "Physgun color") as color|null effects_color = choised_color diff --git a/modular_zubbers/code/modules/debug_tools/phystool.dm b/modular_zubbers/code/modules/debug_tools/phystool.dm index d491c66de99..0867947ef96 100644 --- a/modular_zubbers/code/modules/debug_tools/phystool.dm +++ b/modular_zubbers/code/modules/debug_tools/phystool.dm @@ -39,7 +39,7 @@ return . += span_notice(selected_mode.desc) -/obj/item/phystool/AltClick(mob/user) +/obj/item/phystool/click_alt(mob/user) . = ..() if(selected_mode) qdel(selected_mode) diff --git a/modular_zubbers/code/modules/hydroponics/gene_modder.dm b/modular_zubbers/code/modules/hydroponics/gene_modder.dm index 27bec35eb8d..ae2c60fabd6 100644 --- a/modular_zubbers/code/modules/hydroponics/gene_modder.dm +++ b/modular_zubbers/code/modules/hydroponics/gene_modder.dm @@ -260,7 +260,7 @@ /obj/machinery/plantgenes/Topic(href, list/href_list) if(..()) return - usr.set_machine(src) +// usr.set_machine(src) if(href_list["eject_seed"] && !operation) var/obj/item/I = usr.get_active_held_item() diff --git a/modular_zubbers/maps/biodome/pride_flags.dm b/modular_zubbers/maps/biodome/pride_flags.dm index 419bea39bf4..d4b118235c2 100644 --- a/modular_zubbers/maps/biodome/pride_flags.dm +++ b/modular_zubbers/maps/biodome/pride_flags.dm @@ -17,7 +17,7 @@ icon_state = "flag_pride" item_flag = /obj/item/sign/flag/pride/gay -/obj/structure/sign/flag/pride/gay/AltClick(mob/user) +/obj/structure/sign/flag/pride/gay/click_alt(mob/user) icon_state = "flag_pride_vertical" .=..() @@ -27,7 +27,7 @@ icon_state = "flag_ace" item_flag = /obj/item/sign/flag/pride/ace -/obj/structure/sign/flag/pride/ace/AltClick(mob/user) +/obj/structure/sign/flag/pride/ace/click_alt(mob/user) icon_state = "flag_ace_vertical" .=..() @@ -37,7 +37,7 @@ icon_state = "flag_bi" item_flag = /obj/item/sign/flag/pride/bi -/obj/structure/sign/flag/pride/bi/AltClick(mob/user) +/obj/structure/sign/flag/pride/bi/click_alt(mob/user) icon_state = "flag_bi_vertical" .=..() @@ -47,7 +47,7 @@ icon_state = "flag_lesbian" item_flag = /obj/item/sign/flag/pride/lesbian -/obj/structure/sign/flag/pride/lesbian/AltClick(mob/user) +/obj/structure/sign/flag/pride/lesbian/click_alt(mob/user) icon_state = "flag_lesbian_vertical" .=..() @@ -57,7 +57,7 @@ icon_state = "flag_pan" item_flag = /obj/item/sign/flag/pride/pan -/obj/structure/sign/flag/pride/pan/AltClick(mob/user) +/obj/structure/sign/flag/pride/pan/click_alt(mob/user) icon_state = "flag_pan_vertical" .=..() @@ -67,7 +67,7 @@ icon_state = "flag_trans" item_flag = /obj/item/sign/flag/pride/trans -/obj/structure/sign/flag/pride/trans/AltClick(mob/user) +/obj/structure/sign/flag/pride/trans/click_alt(mob/user) icon_state = "flag_trans_vertical" .=..() @@ -112,4 +112,4 @@ name = "folded trans pride flag" desc = "The folded flag of trans pride." icon_state = "folded_pride_trans" - sign_path = /obj/structure/sign/flag/pride/trans \ No newline at end of file + sign_path = /obj/structure/sign/flag/pride/trans diff --git a/modular_zubbers/modules/arcades/code/loot/~arcade_weights_final.dm b/modular_zubbers/modules/arcades/code/loot/~arcade_weights_final.dm index a3b5c92f3a5..7e15bf44cc1 100644 --- a/modular_zubbers/modules/arcades/code/loot/~arcade_weights_final.dm +++ b/modular_zubbers/modules/arcades/code/loot/~arcade_weights_final.dm @@ -4,4 +4,5 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list( GLOB.arcade_prize_pool_mechanical = 1000, GLOB.arcade_prize_pool_special = 250, GLOB.arcade_prize_pool_oh_god = 1 -)) \ No newline at end of file +)) + // UNTICKED, COME BACK LATER AND OVERRIDE diff --git a/modular_zubbers/modules/blooper/bark.dm b/modular_zubbers/modules/blooper/bark.dm index 737b114f0cf..37e1425d4fa 100644 --- a/modular_zubbers/modules/blooper/bark.dm +++ b/modular_zubbers/modules/blooper/bark.dm @@ -36,9 +36,9 @@ GLOBAL_VAR_INIT(blooper_allowed, TRUE) // For administrators message_admins("[key_name_admin(usr)] toggled Voice Barks.") SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Voice Bark", "[GLOB.blooper_allowed ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc! -/world/AVerbsAdmin() +/* /world/AVerbsAdmin() . = ..() - return . + /datum/admins/proc/toggleblooper + return . + /datum/admins/proc/toggleblooper */ /proc/toggle_blooper(toggle = null) if(toggle != null) diff --git a/modular_zubbers/modules/bubber_tram/code/moonstation_tram.dm b/modular_zubbers/modules/bubber_tram/code/moonstation_tram.dm index ca001ff0b5b..ec570dc317f 100644 --- a/modular_zubbers/modules/bubber_tram/code/moonstation_tram.dm +++ b/modular_zubbers/modules/bubber_tram/code/moonstation_tram.dm @@ -22,7 +22,7 @@ name = "moon rover controller" desc = "Unlike the iconic moon rover of yesteryears, our tram is here to remind you that even in space, mediocrity finds a way." configured_transport_id = MOONSTATION_LINE_1 - obj_flags = parent_type::obj_flags | NO_DECONSTRUCTION + obj_flags = parent_type::obj_flags | NO_DEBRIS_AFTER_DECONSTRUCTION /obj/machinery/transport/destination_sign/moonstation icon = 'modular_zubbers/modules/bubber_tram/icons/tram_display.dmi' diff --git a/modular_zubbers/modules/shelves/shelf.dm b/modular_zubbers/modules/shelves/shelf.dm index be027cca9eb..7e0016e442f 100644 --- a/modular_zubbers/modules/shelves/shelf.dm +++ b/modular_zubbers/modules/shelves/shelf.dm @@ -48,7 +48,7 @@ . += " [icon2html(crate, user)] [crate]" /obj/structure/cargo_shelf/attackby(obj/item/item, mob/living/user, params) - if (item.tool_behaviour == TOOL_WRENCH && !(flags_1 & NO_DECONSTRUCTION)) + if (item.tool_behaviour == TOOL_WRENCH && !(flags_1 & NO_DEBRIS_AFTER_DECONSTRUCTION)) item.play_tool_sound(src) if(do_after(user, 3 SECONDS, target = src)) deconstruct(TRUE) @@ -133,7 +133,7 @@ crate.visible_message(span_warning("[crate] falls apart!")) crate.deconstruct() shelf_contents[shelf_contents.Find(crate)] = null - if(!(flags_1 & NO_DECONSTRUCTION)) + if(!(flags_1 & NO_DEBRIS_AFTER_DECONSTRUCTION)) density = FALSE var/obj/item/rack_parts/cargo_shelf/newparts = new(loc) transfer_fingerprints_to(newparts) diff --git a/sound/attributions.txt b/sound/attributions.txt index c81aa3e664b..be8df17c535 100644 --- a/sound/attributions.txt +++ b/sound/attributions.txt @@ -140,3 +140,10 @@ https://freesound.org/people/steaq/sounds/560124/ refinery.ogg, smelter.ogg, and wooping_teleport.ogg are all original works by ArcaneMusic, with smelter.ogg using samples from rock_break alongside original sound effects from a warrior electric drill, where refinery and wooping_teleport are modifications of that same electric drill recording. + +paper_flip.ogg is made by gynation from Freesound.org, CC0 +https://freesound.org/people/gynation/sounds/82378/ + +nightmare_poof.ogg and nightmare_reappear.ogg are comprised of breath_01.wav by Nightflame (CC0) and slide-click.wav by Qat (CC0) +https://freesound.org/people/Qat/sounds/108332/ +https://freesound.org/people/Nightflame/sounds/368615/ diff --git a/sound/effects/nightmare_poof.ogg b/sound/effects/nightmare_poof.ogg new file mode 100644 index 00000000000..e8b44685ba4 Binary files /dev/null and b/sound/effects/nightmare_poof.ogg differ diff --git a/sound/effects/nightmare_reappear.ogg b/sound/effects/nightmare_reappear.ogg new file mode 100644 index 00000000000..3dec2006460 Binary files /dev/null and b/sound/effects/nightmare_reappear.ogg differ diff --git a/sound/items/paper_flip.ogg b/sound/items/paper_flip.ogg new file mode 100644 index 00000000000..9e6aca59675 Binary files /dev/null and b/sound/items/paper_flip.ogg differ diff --git a/sound/weapons/zipline_fire.ogg b/sound/weapons/zipline_fire.ogg new file mode 100644 index 00000000000..4ac133897b5 Binary files /dev/null and b/sound/weapons/zipline_fire.ogg differ diff --git a/sound/weapons/zipline_hit.ogg b/sound/weapons/zipline_hit.ogg new file mode 100644 index 00000000000..cf17cbc84d1 Binary files /dev/null and b/sound/weapons/zipline_hit.ogg differ diff --git a/sound/weapons/zipline_mid.ogg b/sound/weapons/zipline_mid.ogg new file mode 100644 index 00000000000..22148f1c594 Binary files /dev/null and b/sound/weapons/zipline_mid.ogg differ diff --git a/strings/antagonist_flavor/spy_objective.json b/strings/antagonist_flavor/spy_objective.json index aa696baad6f..908a8da2b82 100644 --- a/strings/antagonist_flavor/spy_objective.json +++ b/strings/antagonist_flavor/spy_objective.json @@ -8,73 +8,190 @@ "Ensure @pick(location) is @pick(affected) by the end of the shift.", "Ensure no heads of staff @pick(escape) the station.", "Ensure no members of @pick(department) @pick(escape) the station.", - "Ensure no rival @pick(rivals) @pick(escape) the station.", + "Ensure no @pick(rivals) @pick(escape) the station.", + "Ensure no @pick(rivals) succeed in their objectives.", + "Ensure all @pick(rivals) @pick(escape) the station.", + "Ensure all @pick(rivals) succeed in their objectives.", + "Ensure at least some @pick(rivals) leave the shift @pick(affected).", + "Ensure at least some @pick(rivals) do not leave the shift @pick(affected).", + "Ensure at least some @pick(rivals) @pick(escape) the station @pick(affected).", + "Ensure no @pick(rivals) @pick(escape) the station @pick(affected).", + "Ensure the station's @pick(happenings) turn out @pick(affected).", "Frame a crewmember for a crime.", "Free the station's AI from its laws.", "Halt the station's @pick(happenings).", + "Help the station succeed in its @pick(happenings).", "Invoke a mutiny against the heads of staff.", - "Make it difficult, but not impossible to @pick(escape) the station.", + "Invoke a mutiny in @pick(department).", + "Keep everyone out of @pick(location).", + "Make it difficult but not impossible to @pick(escape) the station.", + "Protect the station's @pick(happenings).", "Sabotage the station's power grid or engine.", + "Steal all the @pick(stealables) from @pick(department).", + "Steal all the @pick(stealables) from @pick(location).", "Steal as many @pick(stealables) as you can.", "Take control of the station as the new Captain.", - "Take hostages of high value crewmembers and demand a ransom." + "Take hostages of high value crewmembers and demand a ransom.", + "Terrorize @pick(department) enough to be attacked on sight.", + "Terrorize @pick(rivals) enough to be branded a hero." ], "department": [ - "Security", + "Command", "Engineering", "Medical", "Science", + "Security", + "Service", "Supply" ], "location": [ + "atmospherics", + "departures", "engineering", "genetics", "hydroponics", "medbay", + "the armory", "the bar", "the bridge", "the brig", "the cargo bay", + "the Central Primary hallway", + "the courtroom", "the chapel", + "the garden", + "the holodeck", "the kitchen", "the library", + "the mining outpost", + "the vault", + "virology", "xenobiology" ], "happenings": [ - "research", + "breakfasts", "cargo operations", "communications", + "efforts to figure something out", + "efforts to make an important decision", + "efforts to solve a crime", + "efforts to solve a murder", + "efforts to start a project", + "efforts to stop a disaster", + "lunches", + "dinners", "genetic research", - "mining operation" + "mech constructions", + "mining operations", + "optional surgeries", + "public gatherings", + "public services", + "research efforts", + "social events", + "xenobiological experiments" ], "affected": [ + "a disaster", "ablaze", + "alive", + "a failure", + "a success", + "better than expected", + "blasted", + "bored", + "boring", "burning", + "busy", + "clean", + "confused", + "confusing", "covered in blood", + "cursed", + "dead", + "dirty", + "disrupted", + "disabled", "demolished", "destroyed", + "devastated", "engulfed in flames", + "exploded", + "exploding", + "free", + "frustrated", + "functional", + "hazardous", + "horrified", + "horrifying", + "in chaos", + "inspired", + "inspiring", + "intact", + "locked down", + "non-functional", "obliterated", + "offended", "on fire", + "optimized", + "peaceful", + "powerful", + "quiet", "ruined", "sabotaged", + "safe", + "scary", + "scandalized", + "serene", + "shattered", + "terrible", + "tranquil", + "unrecognizable", + "vandalized", "wrecked" ], "rivals": [ "agents", + "aliens", + "cowards", + "criminals", + "entertainers", + "extradimensional horrors", + "fanatics", + "foreigners", + "hooligans", + "litterers", + "magic-users", "moles", "operatives", + "rude people", + "sentient non-humanoids", "spies", - "traitors" + "subversives", + "thieves", + "traitors", + "tyrants" ], "stealables": [ + "appliances", + "cargo orders", + "critical pieces of infrastructure", + "decorations", + "floor tiles", + "foods", "items", + "materials", + "medicines", "objects", + "pets", + "public supplies", + "quiet moments", "things", "tools", + "vending machines", "weapons" ], "escape": [ + "abscond from", "depart", "escape", "evacuate", diff --git a/strings/arcade.json b/strings/arcade.json index 584cbc6decd..a97a3d75549 100644 --- a/strings/arcade.json +++ b/strings/arcade.json @@ -79,64 +79,6 @@ "Yuletide" ], - "rpg_action": [ - "Annihilate", - "Ban", - "Defeat", - "Destroy", - "Mutilate", - "Nuke", - "Own", - "Perma", - "Pwn", - "Pulverize", - "Robust", - "Save", - "Stop", - "Strike", - "Valid", - "Yeet" - ], - - "rpg_action_valentines": [ - "Bewitch", - "Crush", - "Cuddle", - "Divorce", - "ERP", - "Romance", - "Seduce", - "Smooch", - "Titillate" - ], - - "rpg_action_halloween": [ - "Amputate", - "Behead", - "Beware", - "Butcher", - "Dismember", - "Exorcise", - "Frighten", - "Horrify", - "Scare", - "Scythe", - "Slay", - "Spook", - "Vanquish" - ], - - "rpg_action_xmas": [ - "Freeze", - "Jingle", - "Nutcrack", - "Re-gift", - "Snowplow", - "Stuff", - "Unwrap", - "Wassail" - ], - "rpg_enemy": [ "Administrator", "Bloopers", @@ -217,66 +159,6 @@ "Stalking Stocking", "Yeti", "Yuki-Onna" - ], - - "rpg_weapon": [ - "baseball bat", - "bike horn", - "broken bottle", - "chef's knife", - "circular saw", - "claymore", - "cleaver", - "crowbar", - "curator's whip", - "fire axe", - "fire extinguisher", - "full oxygen tank", - "glass shard", - "liz o' nine tails", - "null rod", - "potted plant", - "rolling pin", - "scalpel", - "screwdriver", - "stunprod", - "toolbox", - "welder" - ], - - "rpg_weapon_valentines": [ - "bouquet of deathnettles", - "candy-heart shotgun", - "cupid's arrow", - "declaration of anguished feelings", - "razor-sharp breakup letter", - "still-beating heart", - "thorny rose", - "toolbox of chocolates" - ], - - "rpg_weapon_halloween": [ - "chainsaw", - "heavy gravestone", - "lit jack-o-lantern", - "machete", - "silver dagger", - "skeleton femur", - "spectral blade", - "wooden stake" - ], - - "rpg_weapon_xmas": [ - "bike horn playing carols", - "blunt fruitcake", - "box cutter", - "Christmas-light garrotte", - "festivus polearm", - "rejected present", - "sharpened icicle", - "sprig of mistletoe", - "thrown snowball", - "whole Christmas tree" ] } diff --git a/tgstation.dme b/tgstation.dme index 463762e4954..00794ab14bd 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -31,6 +31,7 @@ #include "code\__DEFINES\actions.dm" #include "code\__DEFINES\actionspeed_modification.dm" #include "code\__DEFINES\admin.dm" +#include "code\__DEFINES\admin_verb.dm" #include "code\__DEFINES\adventure.dm" #include "code\__DEFINES\airlock.dm" #include "code\__DEFINES\alarm.dm" @@ -40,7 +41,7 @@ #include "code\__DEFINES\antagonists.dm" #include "code\__DEFINES\apc_defines.dm" #include "code\__DEFINES\appearance.dm" -#include "code\__DEFINES\area_editor.dm" +#include "code\__DEFINES\arcades.dm" #include "code\__DEFINES\art.dm" #include "code\__DEFINES\assemblies.dm" #include "code\__DEFINES\assert.dm" @@ -60,6 +61,7 @@ #include "code\__DEFINES\chat.dm" #include "code\__DEFINES\chat_filter.dm" #include "code\__DEFINES\cleaning.dm" +#include "code\__DEFINES\click.dm" #include "code\__DEFINES\client.dm" #include "code\__DEFINES\clothing.dm" #include "code\__DEFINES\colors.dm" @@ -614,6 +616,7 @@ #include "code\__HELPERS\~skyrat_helpers\unsorted.dm" #include "code\_globalvars\_regexes.dm" #include "code\_globalvars\admin.dm" +#include "code\_globalvars\arcade.dm" #include "code\_globalvars\bitfields.dm" #include "code\_globalvars\colorvars.dm" #include "code\_globalvars\configuration.dm" @@ -660,6 +663,7 @@ #include "code\_onclick\adjacent.dm" #include "code\_onclick\ai.dm" #include "code\_onclick\click.dm" +#include "code\_onclick\click_alt.dm" #include "code\_onclick\cyborg.dm" #include "code\_onclick\drag_drop.dm" #include "code\_onclick\item_attack.dm" @@ -721,6 +725,7 @@ #include "code\controllers\configuration\entries\resources.dm" #include "code\controllers\subsystem\achievements.dm" #include "code\controllers\subsystem\addiction.dm" +#include "code\controllers\subsystem\admin_verbs.dm" #include "code\controllers\subsystem\ai_controllers.dm" #include "code\controllers\subsystem\air.dm" #include "code\controllers\subsystem\ambience.dm" @@ -856,7 +861,6 @@ #include "code\controllers\subsystem\processing\greyscale.dm" #include "code\controllers\subsystem\processing\instruments.dm" #include "code\controllers\subsystem\processing\obj.dm" -#include "code\controllers\subsystem\processing\obj_tab_items.dm" #include "code\controllers\subsystem\processing\plumbing.dm" #include "code\controllers\subsystem\processing\processing.dm" #include "code\controllers\subsystem\processing\projectiles.dm" @@ -1230,6 +1234,7 @@ #include "code\datums\components\manual_breathing.dm" #include "code\datums\components\manual_heart.dm" #include "code\datums\components\marionette.dm" +#include "code\datums\components\martial_art_giver.dm" #include "code\datums\components\mind_linker.dm" #include "code\datums\components\mirv.dm" #include "code\datums\components\mob_chain.dm" @@ -1471,6 +1476,7 @@ #include "code\datums\elements\atmos_requirements.dm" #include "code\datums\elements\atmos_sensitive.dm" #include "code\datums\elements\attack_equip.dm" +#include "code\datums\elements\attack_zone_randomiser.dm" #include "code\datums\elements\backblast.dm" #include "code\datums\elements\bane.dm" #include "code\datums\elements\basic_eating.dm" @@ -1552,6 +1558,7 @@ #include "code\datums\elements\light_blocking.dm" #include "code\datums\elements\light_eaten.dm" #include "code\datums\elements\light_eater.dm" +#include "code\datums\elements\living_limb_initialiser.dm" #include "code\datums\elements\loomable.dm" #include "code\datums\elements\mirage_border.dm" #include "code\datums\elements\mob_access.dm" @@ -1571,6 +1578,7 @@ #include "code\datums\elements\pet_bonus.dm" #include "code\datums\elements\plant_backfire.dm" #include "code\datums\elements\point_of_interest.dm" +#include "code\datums\elements\poster_tearer.dm" #include "code\datums\elements\prevent_attacking_of_types.dm" #include "code\datums\elements\projectile_drop.dm" #include "code\datums\elements\projectile_shield.dm" @@ -1598,6 +1606,7 @@ #include "code\datums\elements\tenacious.dm" #include "code\datums\elements\tiny_mob_hunter.dm" #include "code\datums\elements\tool_flash.dm" +#include "code\datums\elements\tool_renaming.dm" #include "code\datums\elements\toy_talk.dm" #include "code\datums\elements\turf_transparency.dm" #include "code\datums\elements\undertile.dm" @@ -1612,6 +1621,7 @@ #include "code\datums\elements\wall_smasher.dm" #include "code\datums\elements\wall_tearer.dm" #include "code\datums\elements\wall_walker.dm" +#include "code\datums\elements\watery_tile.dm" #include "code\datums\elements\weapon_description.dm" #include "code\datums\elements\weather_listener.dm" #include "code\datums\elements\web_walker.dm" @@ -1758,6 +1768,7 @@ #include "code\datums\quirks\negative_quirks\addict.dm" #include "code\datums\quirks\negative_quirks\all_nighter.dm" #include "code\datums\quirks\negative_quirks\allergic.dm" +#include "code\datums\quirks\negative_quirks\anosmia.dm" #include "code\datums\quirks\negative_quirks\bad_back.dm" #include "code\datums\quirks\negative_quirks\bad_touch.dm" #include "code\datums\quirks\negative_quirks\big_hands.dm" @@ -1839,6 +1850,7 @@ #include "code\datums\quirks\positive_quirks\skittish.dm" #include "code\datums\quirks\positive_quirks\spacer.dm" #include "code\datums\quirks\positive_quirks\spiritual.dm" +#include "code\datums\quirks\positive_quirks\strong_stomach.dm" #include "code\datums\quirks\positive_quirks\tagger.dm" #include "code\datums\quirks\positive_quirks\throwing_arm.dm" #include "code\datums\quirks\positive_quirks\voracious.dm" @@ -2148,7 +2160,10 @@ #include "code\game\machinery\computer\telescreen.dm" #include "code\game\machinery\computer\terminal.dm" #include "code\game\machinery\computer\warrant.dm" -#include "code\game\machinery\computer\arcade\arcade.dm" +#include "code\game\machinery\computer\arcade\_arcade.dm" +#include "code\game\machinery\computer\arcade\amputation.dm" +#include "code\game\machinery\computer\arcade\battle.dm" +#include "code\game\machinery\computer\arcade\battle_gear.dm" #include "code\game\machinery\computer\arcade\orion.dm" #include "code\game\machinery\computer\arcade\orion_event.dm" #include "code\game\machinery\computer\atmos_computers\__identifiers.dm" @@ -2231,6 +2246,7 @@ #include "code\game\objects\buckling.dm" #include "code\game\objects\empulse.dm" #include "code\game\objects\items.dm" +#include "code\game\objects\items_reskin.dm" #include "code\game\objects\obj_defense.dm" #include "code\game\objects\objs.dm" #include "code\game\objects\structures.dm" @@ -2805,6 +2821,7 @@ #include "code\game\objects\structures\gym\weight_machine_action.dm" #include "code\game\objects\structures\icemoon\cave_entrance.dm" #include "code\game\objects\structures\lavaland\geyser.dm" +#include "code\game\objects\structures\lavaland\gulag_vent.dm" #include "code\game\objects\structures\lavaland\necropolis_tendril.dm" #include "code\game\objects\structures\lavaland\ore_vent.dm" #include "code\game\objects\structures\plaques\_plaques.dm" @@ -2877,7 +2894,6 @@ #include "code\modules\admin\admin_pda_message.dm" #include "code\modules\admin\admin_ranks.dm" #include "code\modules\admin\admin_verbs.dm" -#include "code\modules\admin\adminmenu.dm" #include "code\modules\admin\antag_panel.dm" #include "code\modules\admin\chat_commands.dm" #include "code\modules\admin\check_antagonists.dm" @@ -2937,6 +2953,8 @@ #include "code\modules\admin\smites\smite.dm" #include "code\modules\admin\smites\supply_pod.dm" #include "code\modules\admin\smites\supply_pod_quick.dm" +#include "code\modules\admin\verb_datums\_admin_verb_datum.dm" +#include "code\modules\admin\verb_datums\_admin_verb_holder.dm" #include "code\modules\admin\verbs\admin.dm" #include "code\modules\admin\verbs\admin_newscaster.dm" #include "code\modules\admin\verbs\adminevents.dm" @@ -2991,6 +3009,7 @@ #include "code\modules\admin\verbs\server.dm" #include "code\modules\admin\verbs\shuttlepanel.dm" #include "code\modules\admin\verbs\spawnobjasmob.dm" +#include "code\modules\admin\verbs\special_verbs.dm" #include "code\modules\admin\verbs\lua\_hooks.dm" #include "code\modules\admin\verbs\lua\_wrappers.dm" #include "code\modules\admin\verbs\lua\helpers.dm" @@ -3405,6 +3424,7 @@ #include "code\modules\asset_cache\assets\fontawesome.dm" #include "code\modules\asset_cache\assets\genetics.dm" #include "code\modules\asset_cache\assets\headers.dm" +#include "code\modules\asset_cache\assets\icon_ref_map.dm" #include "code\modules\asset_cache\assets\inventory.dm" #include "code\modules\asset_cache\assets\irv.dm" #include "code\modules\asset_cache\assets\jquery.dm" @@ -4459,6 +4479,7 @@ #include "code\modules\library\skill_learning\skillchip.dm" #include "code\modules\library\skill_learning\job_skillchips\_job.dm" #include "code\modules\library\skill_learning\job_skillchips\chef.dm" +#include "code\modules\library\skill_learning\job_skillchips\clown.dm" #include "code\modules\library\skill_learning\job_skillchips\janitor.dm" #include "code\modules\library\skill_learning\job_skillchips\miner.dm" #include "code\modules\library\skill_learning\job_skillchips\psychologist.dm" @@ -4487,6 +4508,13 @@ #include "code\modules\logging\categories\log_category_silo.dm" #include "code\modules\logging\categories\log_category_target_zone_switch.dm" #include "code\modules\logging\categories\log_category_uplink.dm" +#include "code\modules\lootpanel\_lootpanel.dm" +#include "code\modules\lootpanel\contents.dm" +#include "code\modules\lootpanel\handlers.dm" +#include "code\modules\lootpanel\misc.dm" +#include "code\modules\lootpanel\search_object.dm" +#include "code\modules\lootpanel\ss_looting.dm" +#include "code\modules\lootpanel\ui.dm" #include "code\modules\mafia\_defines.dm" #include "code\modules\mafia\controller.dm" #include "code\modules\mafia\controller_ui.dm" @@ -4613,6 +4641,7 @@ #include "code\modules\mining\boulder_processing\brm.dm" #include "code\modules\mining\boulder_processing\refinery.dm" #include "code\modules\mining\equipment\explorer_gear.dm" +#include "code\modules\mining\equipment\grapple_gun.dm" #include "code\modules\mining\equipment\kheiral_cuffs.dm" #include "code\modules\mining\equipment\kinetic_crusher.dm" #include "code\modules\mining\equipment\lazarus_injector.dm" @@ -8712,7 +8741,6 @@ #include "modular_zubbers\modules\arcades\code\loot\arcade_weights_oh_god.dm" #include "modular_zubbers\modules\arcades\code\loot\arcade_weights_special.dm" #include "modular_zubbers\modules\arcades\code\loot\arcade_weights_toy.dm" -#include "modular_zubbers\modules\arcades\code\loot\~arcade_weights_final.dm" #include "modular_zubbers\modules\arcades\code\minesweeper\minesweeper.dm" #include "modular_zubbers\modules\arcades\code\overrides\spawners.dm" #include "modular_zubbers\modules\ashwalkers\code\effects\ash_rituals.dm" diff --git a/tgui/packages/common/collections.ts b/tgui/packages/common/collections.ts index 5bfcee85884..9aed42557dc 100644 --- a/tgui/packages/common/collections.ts +++ b/tgui/packages/common/collections.ts @@ -12,33 +12,36 @@ * If collection is 'null' or 'undefined', it will be returned "as is" * without emitting any errors (which can be useful in some cases). */ -export const filter = - (iterateeFn: (input: T, index: number, collection: T[]) => boolean) => - (collection: T[]): T[] => { - if (collection === null || collection === undefined) { - return collection; - } - if (Array.isArray(collection)) { - const result: T[] = []; - for (let i = 0; i < collection.length; i++) { - const item = collection[i]; - if (iterateeFn(item, i, collection)) { - result.push(item); - } +export const filter = ( + collection: T[], + iterateeFn: (input: T, index: number, collection: T[]) => boolean, +): T[] => { + if (collection === null || collection === undefined) { + return collection; + } + if (Array.isArray(collection)) { + const result: T[] = []; + for (let i = 0; i < collection.length; i++) { + const item = collection[i]; + if (iterateeFn(item, i, collection)) { + result.push(item); } - return result; } - throw new Error(`filter() can't iterate on type ${typeof collection}`); - }; + return result; + } + throw new Error(`filter() can't iterate on type ${typeof collection}`); +}; type MapFunction = { ( + collection: T[], iterateeFn: (value: T, index: number, collection: T[]) => U, - ): (collection: T[]) => U[]; + ): U[]; ( + collection: Record, iterateeFn: (value: T, index: K, collection: Record) => U, - ): (collection: Record) => U[]; + ): U[]; }; /** @@ -49,44 +52,30 @@ type MapFunction = { * If collection is 'null' or 'undefined', it will be returned "as is" * without emitting any errors (which can be useful in some cases). */ -export const map: MapFunction = - (iterateeFn) => - (collection: T[]): U[] => { - if (collection === null || collection === undefined) { - return collection; - } - - if (Array.isArray(collection)) { - return collection.map(iterateeFn); - } - - if (typeof collection === 'object') { - return Object.entries(collection).map(([key, value]) => { - return iterateeFn(value, key, collection); - }); - } - - throw new Error(`map() can't iterate on type ${typeof collection}`); - }; - -/** - * Given a collection, will run each element through an iteratee function. - * Will then filter out undefined values. - */ -export const filterMap = ( - collection: T[], - iterateeFn: (value: T) => U | undefined, -): U[] => { - const finalCollection: U[] = []; - - for (const value of collection) { - const output = iterateeFn(value); - if (output !== undefined) { - finalCollection.push(output); - } +export const map: MapFunction = (collection, iterateeFn) => { + if (collection === null || collection === undefined) { + return collection; } - return finalCollection; + if (Array.isArray(collection)) { + const result: unknown[] = []; + for (let i = 0; i < collection.length; i++) { + result.push(iterateeFn(collection[i], i, collection)); + } + return result; + } + + if (typeof collection === 'object') { + const result: unknown[] = []; + for (let i in collection) { + if (Object.prototype.hasOwnProperty.call(collection, i)) { + result.push(iterateeFn(collection[i], i, collection)); + } + } + return result; + } + + throw new Error(`map() can't iterate on type ${typeof collection}`); }; const COMPARATOR = (objA, objB) => { @@ -112,39 +101,38 @@ const COMPARATOR = (objA, objB) => { * * Iteratees are called with one argument (value). */ -export const sortBy = - (...iterateeFns: ((input: T) => unknown)[]) => - (array: T[]): T[] => { - if (!Array.isArray(array)) { - return array; - } - let length = array.length; - // Iterate over the array to collect criteria to sort it by - let mappedArray: { - criteria: unknown[]; - value: T; - }[] = []; - for (let i = 0; i < length; i++) { - const value = array[i]; - mappedArray.push({ - criteria: iterateeFns.map((fn) => fn(value)), - value, - }); - } - // Sort criteria using the base comparator - mappedArray.sort(COMPARATOR); +export const sortBy = ( + array: T[], + ...iterateeFns: ((input: T) => unknown)[] +): T[] => { + if (!Array.isArray(array)) { + return array; + } + let length = array.length; + // Iterate over the array to collect criteria to sort it by + let mappedArray: { + criteria: unknown[]; + value: T; + }[] = []; + for (let i = 0; i < length; i++) { + const value = array[i]; + mappedArray.push({ + criteria: iterateeFns.map((fn) => fn(value)), + value, + }); + } + // Sort criteria using the base comparator + mappedArray.sort(COMPARATOR); - // Unwrap values - const values: T[] = []; - while (length--) { - values[length] = mappedArray[length].value; - } - return values; - }; + // Unwrap values + const values: T[] = []; + while (length--) { + values[length] = mappedArray[length].value; + } + return values; +}; -export const sort = sortBy(); - -export const sortStrings = sortBy(); +export const sort = (array: T[]): T[] => sortBy(array); /** * Returns a range of numbers from start to end, exclusively. @@ -153,12 +141,34 @@ export const sortStrings = sortBy(); export const range = (start: number, end: number): number[] => new Array(end - start).fill(null).map((_, index) => index + start); +type ReduceFunction = { + ( + array: T[], + reducerFn: ( + accumulator: U, + currentValue: T, + currentIndex: number, + array: T[], + ) => U, + initialValue: U, + ): U; + ( + array: T[], + reducerFn: ( + accumulator: T, + currentValue: T, + currentIndex: number, + array: T[], + ) => T, + ): T; +}; + /** * A fast implementation of reduce. */ -export const reduce = (reducerFn, initialValue) => (array) => { +export const reduce: ReduceFunction = (array, reducerFn, initialValue?) => { const length = array.length; - let i; + let i: number; let result; if (initialValue === undefined) { i = 1; @@ -184,15 +194,16 @@ export const reduce = (reducerFn, initialValue) => (array) => { * is determined by the order they occur in the array. The iteratee is * invoked with one argument: value. */ -export const uniqBy = - (iterateeFn?: (value: T) => unknown) => - (array: T[]): T[] => { - const { length } = array; - const result: T[] = []; - const seen: unknown[] = iterateeFn ? [] : result; - let index = -1; - // prettier-ignore - outer: +export const uniqBy = ( + array: T[], + iterateeFn?: (value: T) => unknown, +): T[] => { + const { length } = array; + const result: T[] = []; + const seen: unknown[] = iterateeFn ? [] : result; + let index = -1; + // prettier-ignore + outer: while (++index < length) { let value: T | 0 = array[index]; const computed = iterateeFn ? iterateeFn(value) : value; @@ -214,10 +225,10 @@ export const uniqBy = result.push(value); } } - return result; - }; + return result; +}; -export const uniq = uniqBy(); +export const uniq = (array: T[]): T[] => uniqBy(array); type Zip = { [I in keyof T]: T[I] extends (infer U)[] ? U : never; @@ -247,17 +258,6 @@ export const zip = (...arrays: T): Zip => { return result; }; -/** - * This method is like "zip" except that it accepts iteratee to - * specify how grouped values should be combined. The iteratee is - * invoked with the elements of each group. - */ -export const zipWith = - (iterateeFn: (...values: T[]) => U) => - (...arrays: T[][]): U[] => { - return map((values: T[]) => iterateeFn(...values))(zip(...arrays)); - }; - const binarySearch = ( getKey: (value: T) => U, collection: readonly T[], @@ -293,13 +293,15 @@ const binarySearch = ( return compare > insertingKey ? middle : middle + 1; }; -export const binaryInsertWith = - (getKey: (value: T) => U) => - (collection: readonly T[], value: T) => { - const copy = [...collection]; - copy.splice(binarySearch(getKey, collection, value), 0, value); - return copy; - }; +export const binaryInsertWith = ( + collection: readonly T[], + value: T, + getKey: (value: T) => U, +): T[] => { + const copy = [...collection]; + copy.splice(binarySearch(getKey, collection, value), 0, value); + return copy; +}; /** * This method takes a collection of items and a number, returning a collection @@ -325,7 +327,8 @@ export const paginate = (collection: T[], maxPerPage: number): T[][] => { return pages; }; -const isObject = (obj: unknown) => typeof obj === 'object' && obj !== null; +const isObject = (obj: unknown): obj is object => + typeof obj === 'object' && obj !== null; // Does a deep merge of two objects. DO NOT FEED CIRCULAR OBJECTS!! export const deepMerge = (...objects: any[]): any => { diff --git a/tgui/packages/common/fp.js b/tgui/packages/common/fp.js index ba7df09d407..675e98d807e 100644 --- a/tgui/packages/common/fp.js +++ b/tgui/packages/common/fp.js @@ -23,27 +23,3 @@ export const flow = (...funcs) => (input, ...rest) => { } return output; }; - -/** - * Composes single-argument functions from right to left. - * - * All functions might accept a context in form of additional arguments. - * If the resulting function is called with more than 1 argument, rest of - * the arguments are passed to all functions unchanged. - * - * @param {...Function} funcs The functions to compose - * @returns {Function} A function obtained by composing the argument functions - * from right to left. For example, compose(f, g, h) is identical to doing - * (input, ...rest) => f(g(h(input, ...rest), ...rest), ...rest) - */ -export const compose = (...funcs) => { - if (funcs.length === 0) { - return (arg) => arg; - } - if (funcs.length === 1) { - return funcs[0]; - } - // prettier-ignore - return funcs.reduce((a, b) => (value, ...rest) => - a(b(value, ...rest), ...rest)); -}; diff --git a/tgui/packages/common/vector.js b/tgui/packages/common/vector.js deleted file mode 100644 index b1f85f7429d..00000000000 --- a/tgui/packages/common/vector.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * N-dimensional vector manipulation functions. - * - * Vectors are plain number arrays, i.e. [x, y, z]. - * - * @file - * @copyright 2020 Aleksej Komarov - * @license MIT - */ - -import { map, reduce, zipWith } from './collections'; - -const ADD = (a, b) => a + b; -const SUB = (a, b) => a - b; -const MUL = (a, b) => a * b; -const DIV = (a, b) => a / b; - -export const vecAdd = (...vecs) => { - return reduce((a, b) => zipWith(ADD)(a, b))(vecs); -}; - -export const vecSubtract = (...vecs) => { - return reduce((a, b) => zipWith(SUB)(a, b))(vecs); -}; - -export const vecMultiply = (...vecs) => { - return reduce((a, b) => zipWith(MUL)(a, b))(vecs); -}; - -export const vecDivide = (...vecs) => { - return reduce((a, b) => zipWith(DIV)(a, b))(vecs); -}; - -export const vecScale = (vec, n) => { - return map((x) => x * n)(vec); -}; - -export const vecInverse = (vec) => { - return map((x) => -x)(vec); -}; - -export const vecLength = (vec) => { - return Math.sqrt(reduce(ADD)(zipWith(MUL)(vec, vec))); -}; - -export const vecNormalize = (vec) => { - return vecDivide(vec, vecLength(vec)); -}; diff --git a/tgui/packages/common/vector.ts b/tgui/packages/common/vector.ts new file mode 100644 index 00000000000..c91715a8f99 --- /dev/null +++ b/tgui/packages/common/vector.ts @@ -0,0 +1,51 @@ +/** + * N-dimensional vector manipulation functions. + * + * Vectors are plain number arrays, i.e. [x, y, z]. + * + * @file + * @copyright 2020 Aleksej Komarov + * @license MIT + */ + +import { map, reduce, zip } from './collections'; + +const ADD = (a: number, b: number): number => a + b; +const SUB = (a: number, b: number): number => a - b; +const MUL = (a: number, b: number): number => a * b; +const DIV = (a: number, b: number): number => a / b; + +export type Vector = number[]; + +export const vecAdd = (...vecs: Vector[]): Vector => { + return map(zip(...vecs), (x) => reduce(x, ADD)); +}; + +export const vecSubtract = (...vecs: Vector[]): Vector => { + return map(zip(...vecs), (x) => reduce(x, SUB)); +}; + +export const vecMultiply = (...vecs: Vector[]): Vector => { + return map(zip(...vecs), (x) => reduce(x, MUL)); +}; + +export const vecDivide = (...vecs: Vector[]): Vector => { + return map(zip(...vecs), (x) => reduce(x, DIV)); +}; + +export const vecScale = (vec: Vector, n: number): Vector => { + return map(vec, (x) => x * n); +}; + +export const vecInverse = (vec: Vector): Vector => { + return map(vec, (x) => -x); +}; + +export const vecLength = (vec: Vector): number => { + return Math.sqrt(reduce(vecMultiply(vec, vec), ADD)); +}; + +export const vecNormalize = (vec: Vector): Vector => { + const length = vecLength(vec); + return map(vec, (c) => c / length); +}; diff --git a/tgui/packages/tgui-panel/chat/selectors.ts b/tgui/packages/tgui-panel/chat/selectors.ts index 2908f661264..3c1e0b4f429 100644 --- a/tgui/packages/tgui-panel/chat/selectors.ts +++ b/tgui/packages/tgui-panel/chat/selectors.ts @@ -9,7 +9,7 @@ import { map } from 'common/collections'; export const selectChat = (state) => state.chat; export const selectChatPages = (state) => - map((id: string) => state.chat.pageById[id])(state.chat.pages); + map(state.chat.pages, (id: string) => state.chat.pageById[id]); export const selectCurrentChatPage = (state) => state.chat.pageById[state.chat.currentPageId]; diff --git a/tgui/packages/tgui/backend.ts b/tgui/packages/tgui/backend.ts index c85d5153210..9190d74dbe2 100644 --- a/tgui/packages/tgui/backend.ts +++ b/tgui/packages/tgui/backend.ts @@ -274,10 +274,6 @@ type BackendState = { shared: Record; suspending: boolean; suspended: boolean; - debug?: { - debugLayout: boolean; - kitchenSink: boolean; - }; }; /** diff --git a/tgui/packages/tgui/components/Autofocus.tsx b/tgui/packages/tgui/components/Autofocus.tsx index a0b3f6f7659..403dbe2e965 100644 --- a/tgui/packages/tgui/components/Autofocus.tsx +++ b/tgui/packages/tgui/components/Autofocus.tsx @@ -1,17 +1,23 @@ -import { createRef, PropsWithChildren, useEffect } from 'react'; +import { PropsWithChildren, useEffect, useRef } from 'react'; -export const Autofocus = (props: PropsWithChildren) => { - const ref = createRef(); +/** Used to force the window to steal focus on load. Children optional */ +export function Autofocus(props: PropsWithChildren) { + const { children } = props; + const ref = useRef(null); useEffect(() => { - setTimeout(() => { + const timer = setTimeout(() => { ref.current?.focus(); }, 1); + + return () => { + clearTimeout(timer); + }; }, []); return (
    - {props.children} + {children}
    ); -}; +} diff --git a/tgui/packages/tgui/components/Chart.tsx b/tgui/packages/tgui/components/Chart.tsx index 205dc6fbec1..bc33ff90606 100644 --- a/tgui/packages/tgui/components/Chart.tsx +++ b/tgui/packages/tgui/components/Chart.tsx @@ -4,7 +4,7 @@ * @license MIT */ -import { map, zipWith } from 'common/collections'; +import { map, zip } from 'common/collections'; import { Component, createRef, RefObject } from 'react'; import { Box, BoxProps } from './Box'; @@ -37,8 +37,8 @@ const normalizeData = ( return []; } - const min = zipWith(Math.min)(...data); - const max = zipWith(Math.max)(...data); + const min = map(zip(...data), (p) => Math.min(...p)); + const max = map(zip(...data), (p) => Math.max(...p)); if (rangeX !== undefined) { min[0] = rangeX[0]; @@ -50,11 +50,12 @@ const normalizeData = ( max[1] = rangeY[1]; } - const normalized = map((point: Point) => { - return zipWith((value: number, min: number, max: number, scale: number) => { - return ((value - min) / (max - min)) * scale; - })(point, min, max, scale); - })(data); + const normalized = map(data, (point) => + map( + zip(point, min, max, scale), + ([value, min, max, scale]) => ((value - min) / (max - min)) * scale, + ), + ); return normalized; }; diff --git a/tgui/packages/tgui/components/DmIcon.tsx b/tgui/packages/tgui/components/DmIcon.tsx new file mode 100644 index 00000000000..fb6816576ac --- /dev/null +++ b/tgui/packages/tgui/components/DmIcon.tsx @@ -0,0 +1,72 @@ +import { ReactNode, useEffect, useState } from 'react'; + +import { resolveAsset } from '../assets'; +import { fetchRetry } from '../http'; +import { BoxProps } from './Box'; +import { Image } from './Image'; + +enum Direction { + NORTH = 1, + SOUTH = 2, + EAST = 4, + WEST = 8, + NORTHEAST = NORTH | EAST, + NORTHWEST = NORTH | WEST, + SOUTHEAST = SOUTH | EAST, + SOUTHWEST = SOUTH | WEST, +} + +type Props = { + /** Required: The path of the icon */ + icon: string; + /** Required: The state of the icon */ + icon_state: string; +} & Partial<{ + /** Facing direction. See direction enum. Default is South */ + direction: Direction; + /** Fallback icon. */ + fallback: ReactNode; + /** Frame number. Default is 1 */ + frame: number; + /** Movement state. Default is false */ + movement: boolean; +}> & + BoxProps; + +let refMap: Record | undefined; + +export function DmIcon(props: Props) { + const { + className, + direction = Direction.SOUTH, + fallback, + frame = 1, + icon_state, + icon, + movement = false, + ...rest + } = props; + + const [iconRef, setIconRef] = useState(''); + + const query = `${iconRef}?state=${icon_state}&dir=${direction}&movement=${movement}&frame=${frame}`; + + useEffect(() => { + async function fetchRefMap() { + const response = await fetchRetry(resolveAsset('icon_ref_map.json')); + const data = await response.json(); + refMap = data; + setIconRef(data[icon]); + } + + if (!refMap) { + fetchRefMap(); + } else { + setIconRef(refMap[icon]); + } + }, []); + + if (!iconRef) return fallback; + + return ; +} diff --git a/tgui/packages/tgui/components/Grid.jsx b/tgui/packages/tgui/components/Grid.jsx deleted file mode 100644 index f5593c9e00a..00000000000 --- a/tgui/packages/tgui/components/Grid.jsx +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file - * @copyright 2020 Aleksej Komarov - * @license MIT - */ - -import { Table } from './Table'; - -/** @deprecated */ -export const Grid = (props) => { - const { children, ...rest } = props; - return ( - - {children} -
    - ); -}; - -/** @deprecated */ -export const GridColumn = (props) => { - const { size = 1, style, ...rest } = props; - return ( - - ); -}; - -Grid.Column = GridColumn; diff --git a/tgui/packages/tgui/components/Grid.tsx b/tgui/packages/tgui/components/Grid.tsx new file mode 100644 index 00000000000..91c9256753b --- /dev/null +++ b/tgui/packages/tgui/components/Grid.tsx @@ -0,0 +1,44 @@ +/** + * @file + * @copyright 2020 Aleksej Komarov + * @license MIT + */ + +import { PropsWithChildren } from 'react'; + +import { logger } from '../logging'; +import { BoxProps } from './Box'; +import { Table } from './Table'; + +/** @deprecated Do not use. Use stack instead. */ +export function Grid(props: PropsWithChildren) { + const { children, ...rest } = props; + logger.error('Grid component is deprecated. Use a Stack instead.'); + return ( + + {children} +
    + ); +} + +type Props = Partial<{ + /** Width of the column in percentage. */ + size: number; +}> & + BoxProps; + +/** @deprecated Do not use. Use stack instead. */ +export function GridColumn(props: Props) { + const { size = 1, style, ...rest } = props; + return ( + + ); +} + +Grid.Column = GridColumn; diff --git a/tgui/packages/tgui/components/Image.tsx b/tgui/packages/tgui/components/Image.tsx index 3e1519bfbbf..5d3a943feb0 100644 --- a/tgui/packages/tgui/components/Image.tsx +++ b/tgui/packages/tgui/components/Image.tsx @@ -1,12 +1,14 @@ -import { ReactNode } from 'react'; +import { useRef } from 'react'; import { BoxProps, computeBoxProps } from './Box'; -import { Tooltip } from './Tooltip'; type Props = Partial<{ - fixBlur: boolean; // true is default, this is an ie thing - objectFit: 'contain' | 'cover'; // fill is default - tooltip: ReactNode; + /** True is default, this fixes an ie thing */ + fixBlur: boolean; + /** False by default. Good if you're fetching images on UIs that do not auto update. This will attempt to fix the 'x' icon 5 times. */ + fixErrors: boolean; + /** Fill is default. */ + objectFit: 'contain' | 'cover'; }> & IconUnion & BoxProps; @@ -22,16 +24,18 @@ type IconUnion = src?: string; }; +const maxAttempts = 5; + /** Image component. Use this instead of Box as="img". */ -export const Image = (props: Props) => { +export function Image(props: Props) { const { - className, fixBlur = true, + fixErrors = false, objectFit = 'fill', src, - tooltip, ...rest } = props; + const attempts = useRef(0); const computedProps = computeBoxProps(rest); computedProps['style'] = { @@ -40,11 +44,20 @@ export const Image = (props: Props) => { objectFit, }; - let content = ; + return ( + { + if (fixErrors && attempts.current < maxAttempts) { + const imgElement = event.currentTarget; - if (tooltip) { - content = {content}; - } - - return content; -}; + setTimeout(() => { + imgElement.src = `${src}?attempt=${attempts.current}`; + attempts.current++; + }, 1000); + } + }} + src={src} + {...computedProps} + /> + ); +} diff --git a/tgui/packages/tgui/components/Table.tsx b/tgui/packages/tgui/components/Table.tsx index 87edfbb8fc9..f4dcf6f3f52 100644 --- a/tgui/packages/tgui/components/Table.tsx +++ b/tgui/packages/tgui/components/Table.tsx @@ -64,6 +64,8 @@ type CellProps = Partial<{ colSpan: number; /** Whether this is a header cell. */ header: boolean; + /** Rows for this cell to expand, assuming there is room. */ + rowSpan: number; }> & BoxProps; diff --git a/tgui/packages/tgui/components/index.ts b/tgui/packages/tgui/components/index.ts index 1a5f477d256..fdeb475ed3b 100644 --- a/tgui/packages/tgui/components/index.ts +++ b/tgui/packages/tgui/components/index.ts @@ -17,6 +17,7 @@ export { ColorBox } from './ColorBox'; export { Dialog } from './Dialog'; export { Dimmer } from './Dimmer'; export { Divider } from './Divider'; +export { DmIcon } from './DmIcon'; export { DraggableControl } from './DraggableControl'; export { Dropdown } from './Dropdown'; export { FitText } from './FitText'; diff --git a/tgui/packages/tgui/debug/KitchenSink.jsx b/tgui/packages/tgui/debug/KitchenSink.jsx index d215ab777d8..19044ca98d0 100644 --- a/tgui/packages/tgui/debug/KitchenSink.jsx +++ b/tgui/packages/tgui/debug/KitchenSink.jsx @@ -4,11 +4,12 @@ * @license MIT */ -import { useLocalState } from '../backend'; +import { useState } from 'react'; + import { Flex, Section, Tabs } from '../components'; import { Pane, Window } from '../layouts'; -const r = require.context('../stories', false, /\.stories\.js$/); +const r = require.context('../stories', false, /\.stories\.jsx$/); /** * @returns {{ @@ -22,8 +23,8 @@ const getStories = () => r.keys().map((path) => r(path)); export const KitchenSink = (props) => { const { panel } = props; - const [theme] = useLocalState('kitchenSinkTheme'); - const [pageIndex, setPageIndex] = useLocalState('pageIndex', 0); + const [theme] = useState(null); + const [pageIndex, setPageIndex] = useState(0); const stories = getStories(); const story = stories[pageIndex]; const Layout = panel ? Pane : Window; diff --git a/tgui/packages/tgui/drag.ts b/tgui/packages/tgui/drag.ts index 584666a97a6..0884b1b0bd7 100644 --- a/tgui/packages/tgui/drag.ts +++ b/tgui/packages/tgui/drag.ts @@ -209,7 +209,7 @@ export const dragStartHandler = (event) => { dragPointOffset = vecSubtract( [event.screenX, event.screenY], getWindowPosition(), - ); + ) as [number, number]; // Focus click target (event.target as HTMLElement)?.focus(); document.addEventListener('mousemove', dragMoveHandler); @@ -234,7 +234,10 @@ const dragMoveHandler = (event: MouseEvent) => { } event.preventDefault(); setWindowPosition( - vecSubtract([event.screenX, event.screenY], dragPointOffset), + vecSubtract([event.screenX, event.screenY], dragPointOffset) as [ + number, + number, + ], ); }; @@ -247,7 +250,7 @@ export const resizeStartHandler = dragPointOffset = vecSubtract( [event.screenX, event.screenY], getWindowPosition(), - ); + ) as [number, number]; initialSize = getWindowSize(); // Focus click target (event.target as HTMLElement)?.focus(); @@ -278,7 +281,10 @@ const resizeMoveHandler = (event: MouseEvent) => { ); const delta = vecSubtract(currentOffset, dragPointOffset); // Extra 1x1 area is added to ensure the browser can see the cursor - size = vecAdd(initialSize, vecMultiply(resizeMatrix, delta), [1, 1]); + size = vecAdd(initialSize, vecMultiply(resizeMatrix, delta), [1, 1]) as [ + number, + number, + ]; // Sane window size values size[0] = Math.max(size[0], 150 * pixelRatio); size[1] = Math.max(size[1], 50 * pixelRatio); diff --git a/tgui/packages/tgui/interfaces/AirlockElectronics.tsx b/tgui/packages/tgui/interfaces/AirlockElectronics.tsx index 7e0ebba0bb4..b90e8ac3b57 100644 --- a/tgui/packages/tgui/interfaces/AirlockElectronics.tsx +++ b/tgui/packages/tgui/interfaces/AirlockElectronics.tsx @@ -1,21 +1,31 @@ import { BooleanLike } from 'common/react'; import { useBackend } from '../backend'; -import { Button, Input, LabeledList, Section } from '../components'; +import { Button, Input, LabeledList, Section, Stack } from '../components'; import { Window } from '../layouts'; -import { AccessConfig } from './common/AccessConfig'; +import { AccessConfig, Region } from './common/AccessConfig'; type Data = { - oneAccess: BooleanLike; - unres_direction: number; - passedName: string; - passedCycleId: number; - regions: string[]; accesses: string[]; + oneAccess: BooleanLike; + passedCycleId: number; + passedName: string; + regions: Region[]; shell: BooleanLike; + unres_direction: number; }; -export const AirLockMainSection = (props) => { +export function AirlockElectronics(props) { + return ( + + + + + + ); +} + +export function AirLockMainSection(props) { const { act, data } = useBackend(); const { accesses = [], @@ -28,123 +38,125 @@ export const AirLockMainSection = (props) => { } = data; return ( -
    - - - { - act('set_shell', { on: !shell }); - }} - tooltip="Whether this airlock can have an integrated circuit placed inside of it or not." - /> - - -
    + + +
    + + + { + act('set_shell', { on: !shell }); + }} + tooltip="Whether this airlock can have an integrated circuit placed inside of it or not." + > + Shell + + + + + + + + + + + + + + act('passedName', { + passedName: value, + }) + } + /> + + + + act('passedCycleId', { + passedCycleId: value, + }) + } + /> + + +
    +
    + + + act('set', { + access: ref, + }) + } + grantAll={() => act('grant_all')} + denyAll={() => act('clear_all')} + grantDep={(ref) => + act('grant_region', { + region: ref, + }) + } + denyDep={(ref) => + act('deny_region', { + region: ref, + }) + } + /> + +
    ); -}; - -export const AirlockElectronics = (props) => { - return ( - - - - - - ); -}; +} diff --git a/tgui/packages/tgui/interfaces/ApcControl.jsx b/tgui/packages/tgui/interfaces/ApcControl.jsx index acf46f9f0b8..fb29c78032d 100644 --- a/tgui/packages/tgui/interfaces/ApcControl.jsx +++ b/tgui/packages/tgui/interfaces/ApcControl.jsx @@ -160,18 +160,21 @@ const ApcControlScene = (props) => { const [sortByField] = useLocalState('sortByField', 'name'); const apcs = flow([ - map((apc, i) => ({ - ...apc, - // Generate a unique id - id: apc.name + i, - })), - sortByField === 'name' && sortBy((apc) => apc.name), - sortByField === 'charge' && sortBy((apc) => -apc.charge), + (apcs) => + map(apcs, (apc, i) => ({ + ...apc, + // Generate a unique id + id: apc.name + i, + })), + sortByField === 'name' && ((apcs) => sortBy(apcs, (apc) => apc.name)), + sortByField === 'charge' && ((apcs) => sortBy(apcs, (apc) => -apc.charge)), sortByField === 'draw' && - sortBy( - (apc) => -powerRank(apc.load), - (apc) => -parseFloat(apc.load), - ), + ((apcs) => + sortBy( + apcs, + (apc) => -powerRank(apc.load), + (apc) => -parseFloat(apc.load), + )), ])(data.apcs); return ( @@ -255,14 +258,11 @@ const ApcControlScene = (props) => { const LogPanel = (props) => { const { data } = useBackend(); - const logs = flow([ - map((line, i) => ({ - ...line, - // Generate a unique id - id: line.entry + i, - })), - (logs) => logs.reverse(), - ])(data.logs); + const logs = map(data.logs, (line, i) => ({ + ...line, + // Generate a unique id + id: line.entry + i, + })).reverse(); return ( {logs.map((line) => ( diff --git a/tgui/packages/tgui/interfaces/AtmosControlPanel.jsx b/tgui/packages/tgui/interfaces/AtmosControlPanel.jsx index 84d0ff08def..c39778c410f 100644 --- a/tgui/packages/tgui/interfaces/AtmosControlPanel.jsx +++ b/tgui/packages/tgui/interfaces/AtmosControlPanel.jsx @@ -1,5 +1,4 @@ import { map, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { useBackend } from '../backend'; import { Box, Button, Flex, Section, Table } from '../components'; @@ -7,14 +6,14 @@ import { Window } from '../layouts'; export const AtmosControlPanel = (props) => { const { act, data } = useBackend(); - const groups = flow([ - map((group, i) => ({ + const groups = sortBy( + map(data.excited_groups, (group, i) => ({ ...group, // Generate a unique id id: group.area + i, })), - sortBy((group) => group.id), - ])(data.excited_groups); + (group) => group.id, + ); return (
    diff --git a/tgui/packages/tgui/interfaces/BattleArcade.tsx b/tgui/packages/tgui/interfaces/BattleArcade.tsx new file mode 100644 index 00000000000..a400628575f --- /dev/null +++ b/tgui/packages/tgui/interfaces/BattleArcade.tsx @@ -0,0 +1,243 @@ +import { resolveAsset } from '../assets'; +import { useBackend } from '../backend'; +import { Box, Button, Image, Section } from '../components'; +import { Window } from '../layouts'; + +type Data = { + all_worlds: string[]; + attack_types: AttackTypeData[]; + max_hp: number; + max_mp: number; + ui_panel: string; + feedback_message: string; + player_current_world: string; + unlocked_world_modifier: number; + latest_unlocked_world_position: number; + player_gold: number; + player_current_hp: number; + player_current_mp: number; + enemy_icon_id: string; + enemy_name: string; + enemy_max_hp: number; + enemy_hp: number; + enemy_mp: number; + cost_of_items: number; + equipped_gear: EquippedGear[]; + shop_items: string[]; +}; + +type AttackTypeData = { + name: string; + tooltip: string; +}; + +type EquippedGear = { + name: string; + slot: string; +}; + +export const BattleArcade = (props) => { + const { act, data } = useBackend(); + const { + ui_panel, + player_current_hp, + player_current_mp, + max_hp, + max_mp, + player_gold, + equipped_gear = [], + } = data; + return ( + + +
    + Player stats
    HP:{' '} + + {player_current_hp}/{max_hp} + {' '} + | MP:{' '} + + {player_current_mp}/{max_mp} + {' '} + | {player_gold || 0}G
    + {!equipped_gear.length && 'No gear equipped!'} + {equipped_gear.map((gear, index) => ( + <> + {gear.slot}: {gear.name}
    + + ))} +
    + {ui_panel === 'Shop' ? ( + + ) : ui_panel === 'World Map' ? ( + + ) : ui_panel === 'Battle' ? ( + + ) : ui_panel === 'Between Battle' ? ( + + ) : ( + + )} +
    +
    + ); +}; + +const ShopPanel = (props) => { + const { act, data } = useBackend(); + const { shop_items, cost_of_items, unlocked_world_modifier } = data; + return ( +
    + Welcome to the Inn! + + + Feel free to browse our wares, or take a nap. I'll be here to + ensure you'll get a good night's rest without worry of + ambushing or robbery. + + {shop_items.map((item, index) => ( + + ))} + + +
    + ); +}; + +const WorldMapPanel = (props) => { + const { act, data } = useBackend(); + const { all_worlds, latest_unlocked_world_position } = data; + return ( +
    + + + {all_worlds.map((world, index) => ( + + ))} +
    + ); +}; + +const BattlePanel = (props) => { + const { act, data } = useBackend(); + const { + attack_types, + enemy_icon_id, + enemy_name, + enemy_max_hp, + enemy_hp, + enemy_mp, + feedback_message, + } = data; + return ( +
    + {feedback_message && {feedback_message}} + + {enemy_name}'s HP: {enemy_hp}/{enemy_max_hp} + + + {enemy_name}'s MP: {enemy_mp} + + + {attack_types.map((attack, index) => ( + + ))} + act('flee')} + > + Flee (Lose half your Gold) + +
    + ); +}; + +const BetweenBattlePanel = (props) => { + const { act, data } = useBackend(); + return ( +
    + + + As night sets, you can choose to rest. This will restore your health and + mana to full before the next battle, but you may also be ambushed, + forcing you into the next fight without any additional healing. + + + + +
    + ); +}; + +const GameOverPanel = (props) => { + const { act, data } = useBackend(); + return ( +
    + + Game Over + + + + +
    + ); +}; diff --git a/tgui/packages/tgui/interfaces/Blueprints.tsx b/tgui/packages/tgui/interfaces/Blueprints.tsx new file mode 100644 index 00000000000..644412a9a77 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Blueprints.tsx @@ -0,0 +1,186 @@ +import { BooleanLike } from 'common/react'; + +import { useBackend } from '../backend'; +import { Box, Button, Divider, Section, Stack } from '../components'; +import { Window } from '../layouts'; + +type Data = { + area_notice: string; + area_name: string; + wire_data: WireData[]; + legend: string; + legend_viewing_list: string; + legend_off: string; + fluff_notice: string; + station_name: string; + wires_name: string; + wire_devices: WireDevices[]; + viewing: BooleanLike; +}; + +type WireDevices = { + name: string; + ref: string; +}; + +type WireData = { + color: string; + message: string; +}; + +export const Blueprints = () => { + const { act, data } = useBackend(); + const { legend, legend_viewing_list, legend_off } = data; + + return ( + + + {legend === legend_viewing_list ? ( + + ) : legend === legend_off ? ( + + ) : ( + + )} + + + ); +}; + +const WireList = () => { + const { act, data } = useBackend(); + const { wire_devices = [] } = data; + + return ( +
    + + + {wire_devices.map((wire) => ( + + ))} + +
    + ); +}; + +const WireArea = () => { + const { act, data } = useBackend(); + const { wires_name, wire_data = [] } = data; + + return ( +
    + + {wires_name} wires: + {wire_data.map((wire) => ( + + {wire.color}:{' '} + {wire.message} + + ))} +
    + ); +}; + +const MainMenu = () => { + const { act, data } = useBackend(); + const { area_notice, area_name, fluff_notice, station_name, viewing } = data; + + return ( +
    + + {fluff_notice} + + + + {area_notice} + + + + + + + + + + + + {viewing ? ( + <> + + + + + + + + ) : ( + + + + )} + +
    + ); +}; diff --git a/tgui/packages/tgui/interfaces/BluespaceSender.tsx b/tgui/packages/tgui/interfaces/BluespaceSender.tsx index 24e88f6ef5d..c8c9e47b0c7 100644 --- a/tgui/packages/tgui/interfaces/BluespaceSender.tsx +++ b/tgui/packages/tgui/interfaces/BluespaceSender.tsx @@ -1,5 +1,4 @@ import { filter, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { toFixed } from 'common/math'; import { BooleanLike } from 'common/react'; import { multiline } from 'common/string'; @@ -43,10 +42,10 @@ export const BluespaceSender = (props) => { const { act, data } = useBackend(); const { gas_transfer_rate, credits, bluespace_network_gases = [], on } = data; - const gases: Gas[] = flow([ - filter((gas) => gas.amount >= 0.01), - sortBy((gas) => -gas.amount), - ])(bluespace_network_gases); + const gases: Gas[] = sortBy( + filter(bluespace_network_gases, (gas) => gas.amount >= 0.01), + (gas) => -gas.amount, + ); const gasMax = Math.max(1, ...gases.map((gas) => gas.amount)); diff --git a/tgui/packages/tgui/interfaces/BluespaceVendor.tsx b/tgui/packages/tgui/interfaces/BluespaceVendor.tsx index 3ba8289356b..6ce242e4e48 100644 --- a/tgui/packages/tgui/interfaces/BluespaceVendor.tsx +++ b/tgui/packages/tgui/interfaces/BluespaceVendor.tsx @@ -1,5 +1,4 @@ import { filter, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { toFixed } from 'common/math'; import { BooleanLike } from 'common/react'; import { multiline } from 'common/string'; @@ -50,10 +49,10 @@ export const BluespaceVendor = (props) => { tank_full, } = data; - const gases: Gas[] = flow([ - filter((gas) => gas.amount >= 0.01), - sortBy((gas) => -gas.amount), - ])(bluespace_network_gases); + const gases: Gas[] = sortBy( + filter(bluespace_network_gases, (gas) => gas.amount >= 0.01), + (gas) => -gas.amount, + ); const gasMax = Math.max(1, ...gases.map((gas) => gas.amount)); diff --git a/tgui/packages/tgui/interfaces/CameraConsole.tsx b/tgui/packages/tgui/interfaces/CameraConsole.tsx index adad4f8748e..3dafe1240df 100644 --- a/tgui/packages/tgui/interfaces/CameraConsole.tsx +++ b/tgui/packages/tgui/interfaces/CameraConsole.tsx @@ -1,5 +1,4 @@ -import { filter, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; +import { filter, sort } from 'common/collections'; import { BooleanLike, classes } from 'common/react'; import { createSearch } from 'common/string'; import { useState } from 'react'; @@ -68,15 +67,17 @@ const prevNextCamera = ( * Filters cameras, applies search terms and sorts the alphabetically. */ const selectCameras = (cameras: Camera[], searchText = ''): Camera[] => { - const testSearch = createSearch(searchText, (camera: Camera) => camera.name); + let queriedCameras = filter(cameras, (camera: Camera) => !!camera.name); + if (searchText) { + const testSearch = createSearch( + searchText, + (camera: Camera) => camera.name, + ); + queriedCameras = filter(queriedCameras, testSearch); + } + queriedCameras = sort(queriedCameras); - return flow([ - filter((camera: Camera) => !!camera.name), - // Optional search term - searchText && filter(testSearch), - // Slightly expensive, but way better than sorting in BYOND - sortBy((camera: Camera) => camera), - ])(cameras); + return queriedCameras; }; export const CameraConsole = (props) => { diff --git a/tgui/packages/tgui/interfaces/Cargo.jsx b/tgui/packages/tgui/interfaces/Cargo.jsx index f160970bc51..cbc0f5b112b 100644 --- a/tgui/packages/tgui/interfaces/Cargo.jsx +++ b/tgui/packages/tgui/interfaces/Cargo.jsx @@ -1,5 +1,4 @@ import { filter, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { useBackend, useSharedState } from '../backend'; import { @@ -169,16 +168,17 @@ const CargoStatus = (props) => { const searchForSupplies = (supplies, search) => { search = search.toLowerCase(); - return flow([ - (categories) => categories.flatMap((category) => category.packs), + const queriedSupplies = sortBy( filter( + supplies.flatMap((category) => category.packs), (pack) => pack.name?.toLowerCase().includes(search.toLowerCase()) || pack.desc?.toLowerCase().includes(search.toLowerCase()), ), - sortBy((pack) => pack.name), - (packs) => packs.slice(0, 25), - ])(supplies); + (pack) => pack.name, + ); + + return queriedSupplies.slice(0, 25); }; export const CargoCatalog = (props) => { diff --git a/tgui/packages/tgui/interfaces/ChemMaster.tsx b/tgui/packages/tgui/interfaces/ChemMaster.tsx index 37b5db33f90..c23ca29f8d9 100644 --- a/tgui/packages/tgui/interfaces/ChemMaster.tsx +++ b/tgui/packages/tgui/interfaces/ChemMaster.tsx @@ -18,32 +18,22 @@ import { Tooltip, } from '../components'; import { Window } from '../layouts'; +import { Beaker, BeakerReagent } from './common/BeakerDisplay'; -type Data = { - reagentAnalysisMode: BooleanLike; - analysisData: Analysis; - isPrinting: BooleanLike; - printingProgress: number; - printingTotal: number; - transferMode: BooleanLike; - hasBeaker: BooleanLike; - beakerCurrentVolume: number; - beakerMaxVolume: number; - beakerContents: Reagent[]; - bufferContents: Reagent[]; - bufferCurrentVolume: number; - bufferMaxVolume: number; - categories: Category[]; - selectedContainerRef: string; - selectedContainerVolume: number; - hasContainerSuggestion: BooleanLike; - doSuggestContainer: BooleanLike; - suggestedContainer: string; +type Container = { + icon: string; + ref: string; + name: string; + volume: number; }; -type Analysis = { +type Category = { name: string; - state: string; + containers: Container[]; +}; + +type AnalyzableReagent = BeakerReagent & { + ref: string; pH: number; color: string; description: string; @@ -53,144 +43,162 @@ type Analysis = { addictionTypes: string[]; }; -type Category = { - name: string; - containers: Container[]; -}; +type AnalyzableBeaker = { + contents: AnalyzableReagent[]; +} & Beaker; -type Reagent = { - ref: string; - name: string; - volume: number; -}; - -type Container = { - icon: string; - ref: string; - name: string; - volume: number; +type Data = { + categories: Category[]; + isPrinting: BooleanLike; + printingProgress: number; + printingTotal: number; + maxPrintable: number; + beaker: AnalyzableBeaker; + buffer: AnalyzableBeaker; + isTransfering: BooleanLike; + suggestedContainerRef: string; + selectedContainerRef: string; + selectedContainerVolume: number; }; export const ChemMaster = (props) => { - const { data } = useBackend(); - const { reagentAnalysisMode } = data; + const [analyzedReagent, setAnalyzedReagent] = useState(); + return ( - + - {reagentAnalysisMode ? : } + {analyzedReagent ? ( + setAnalyzedReagent(undefined)} + /> + ) : ( + + setAnalyzedReagent(chemical) + } + /> + )} ); }; -const ChemMasterContent = (props) => { +const ChemMasterContent = (props: { + analyze: (chemical: AnalyzableReagent) => void; +}) => { const { act, data } = useBackend(); const { isPrinting, printingProgress, printingTotal, - transferMode, - hasBeaker, - beakerCurrentVolume, - beakerMaxVolume, - beakerContents, - bufferContents, - bufferCurrentVolume, - bufferMaxVolume, + maxPrintable, + isTransfering, + beaker, + buffer, categories, selectedContainerVolume, - hasContainerSuggestion, - doSuggestContainer, - suggestedContainer, } = data; - const [itemCount, setItemCount] = useState(1); + const [itemCount, setItemCount] = useState(1); + const [showPreferredContainer, setShowPreferredContainer] = + useState(false); + const buffer_contents = buffer.contents; return (
    - - {` / ${beakerMaxVolume} units`} + + {` / ${beaker.maxVolume} units`} - ) } > - {!hasBeaker && ( + {!beaker ? ( No beaker loaded. - )} - {!!hasBeaker && beakerCurrentVolume === 0 && ( + ) : beaker.currentVolume === 0 ? ( Beaker is empty. + ) : ( + + {beaker.contents.map((chemical) => ( + + ))} +
    )} - - {beakerContents.map((chemical) => ( - - ))} -
    - - {` / ${bufferMaxVolume} units`} + + {` / ${buffer.maxVolume} units`} } > - {bufferContents.length === 0 && ( + {buffer_contents.length === 0 ? ( Buffer is empty. + ) : ( + + {buffer_contents.map((chemical) => ( + + ))} +
    )} - - {bufferContents.map((chemical) => ( - - ))} -
    {!isPrinting && (
    + + setShowPreferredContainer((currentValue) => !currentValue) + } + > + Suggest + { setItemCount(value); }} @@ -200,51 +208,36 @@ const ChemMasterContent = (props) => { Math.round( Math.min( selectedContainerVolume, - bufferCurrentVolume / itemCount, + buffer.currentVolume / itemCount, ) * 100, ) / 100 } u. each`} - ) : ( -
    @@ -256,9 +249,10 @@ const ChemMasterContent = (props) => { } > { ); }; -const ReagentEntry = (props) => { +type ReagentProps = { + chemical: AnalyzableReagent; + transferTo: string; + analyze: (chemical: AnalyzableReagent) => void; +}; + +const ReagentEntry = (props: ReagentProps) => { const { data, act } = useBackend(); - const { chemical, transferTo } = props; + const { chemical, transferTo, analyze } = props; const { isPrinting } = data; return ( @@ -295,7 +295,6 @@ const ReagentEntry = (props) => { } > @@ -438,7 +454,6 @@ const AnalysisResults = (props) => {
    {pH} - {state} {color} diff --git a/tgui/packages/tgui/interfaces/CircuitAccessChecker.tsx b/tgui/packages/tgui/interfaces/CircuitAccessChecker.tsx index 0c81311a431..f37414a86f5 100644 --- a/tgui/packages/tgui/interfaces/CircuitAccessChecker.tsx +++ b/tgui/packages/tgui/interfaces/CircuitAccessChecker.tsx @@ -3,11 +3,11 @@ import { BooleanLike } from 'common/react'; import { useBackend } from '../backend'; import { Button, LabeledList } from '../components'; import { Window } from '../layouts'; -import { AccessConfig } from './common/AccessConfig'; +import { AccessConfig, Region } from './common/AccessConfig'; type Data = { oneAccess: BooleanLike; - regions: string[]; + regions: Region[]; accesses: string[]; }; @@ -28,8 +28,8 @@ export const CircuitAccessChecker = (props) => { act('set', { access: ref, diff --git a/tgui/packages/tgui/interfaces/ClockworkSlab.jsx b/tgui/packages/tgui/interfaces/ClockworkSlab.jsx index 6e9eef57d87..7acb39b8713 100644 --- a/tgui/packages/tgui/interfaces/ClockworkSlab.jsx +++ b/tgui/packages/tgui/interfaces/ClockworkSlab.jsx @@ -7,10 +7,10 @@ import { Button, Collapsible, Divider, - Grid, Icon, ProgressBar, Section, + Stack, Table, } from '../components'; import { TableRow } from '../components/Table'; @@ -311,12 +311,12 @@ const ClockworkOverviewStat = (props) => { const { title, iconName, amount, maxAmount, unit, overrideText } = props; return ( - - + + - - {title} - + + {title} + { > {overrideText ? overrideText : amount + ' ' + unit} - - + + ); }; diff --git a/tgui/packages/tgui/interfaces/CommunicationsConsole.jsx b/tgui/packages/tgui/interfaces/CommunicationsConsole.jsx index b6dc5ac272f..0a1306a19d6 100644 --- a/tgui/packages/tgui/interfaces/CommunicationsConsole.jsx +++ b/tgui/packages/tgui/interfaces/CommunicationsConsole.jsx @@ -29,10 +29,12 @@ const SWIPE_NEEDED = 'SWIPE_NEEDED'; const EMAG_SHUTTLE_NOTICE = 'This shuttle is deemed significantly dangerous to the crew, and is only supplied by the Syndicate.'; -const sortShuttles = sortBy( - (shuttle) => !shuttle.emagOnly, - (shuttle) => shuttle.initial_cost, -); +const sortShuttles = (shuttles) => + sortBy( + shuttles, + (shuttle) => !shuttle.emagOnly, + (shuttle) => shuttle.initial_cost, + ); const AlertButton = (props) => { const { act, data } = useBackend(); diff --git a/tgui/packages/tgui/interfaces/ControllerOverview.tsx b/tgui/packages/tgui/interfaces/ControllerOverview.tsx new file mode 100644 index 00000000000..5b5c210b7bb --- /dev/null +++ b/tgui/packages/tgui/interfaces/ControllerOverview.tsx @@ -0,0 +1,245 @@ +import { BooleanLike } from 'common/react'; +import { createSearch } from 'common/string'; +import { useMemo, useState } from 'react'; + +import { useBackend } from '../backend'; +import { + Button, + Collapsible, + Dropdown, + Input, + LabeledList, + Section, + Stack, +} from '../components'; +import { Window } from '../layouts'; + +type SubsystemData = { + name: string; + ref: string; + init_order: number; + last_fire: number; + next_fire: number; + can_fire: BooleanLike; + doesnt_fire: BooleanLike; + cost_ms: number; + tick_usage: number; + tick_overrun: number; + initialized: BooleanLike; + initialization_failure_message: string | undefined; +}; + +type ControllerData = { + world_time: number; + fast_update: BooleanLike; + map_cpu: number; + subsystems: SubsystemData[]; +}; + +const SubsystemView = (props: { data: SubsystemData }) => { + const { act } = useBackend(); + const { data } = props; + const { + name, + ref, + init_order, + last_fire, + next_fire, + can_fire, + doesnt_fire, + cost_ms, + tick_usage, + tick_overrun, + initialized, + initialization_failure_message, + } = data; + + let icon = 'play'; + if (!initialized) { + icon = 'circle-exclamation'; + } else if (doesnt_fire) { + icon = 'check'; + } else if (!can_fire) { + icon = 'pause'; + } + + return ( + { + act('view_variables', { ref: ref }); + }} + /> + } + > + + {init_order} + {last_fire} + {next_fire} + {cost_ms}ms + + {(tick_usage * 0.01).toFixed(2)}% + + + {(tick_overrun * 0.01).toFixed(2)}% + + {initialization_failure_message ? ( + + {initialization_failure_message} + + ) : undefined} + + + ); +}; + +enum SubsystemSortBy { + INIT_ORDER = 'Init Order', + NAME = 'Name', + LAST_FIRE = 'Last Fire', + NEXT_FIRE = 'Next Fire', + TICK_USAGE = 'Tick Usage', + TICK_OVERRUN = 'Tick Overrun', + COST = 'Cost', +} + +const sortSubsystemBy = ( + subsystems: SubsystemData[], + sortBy: SubsystemSortBy, + asending: boolean = true, +) => { + let sorted = subsystems.sort((left, right) => { + switch (sortBy) { + case SubsystemSortBy.INIT_ORDER: + return left.init_order - right.init_order; + case SubsystemSortBy.NAME: + return left.name.localeCompare(right.name); + case SubsystemSortBy.LAST_FIRE: + return left.last_fire - right.last_fire; + case SubsystemSortBy.NEXT_FIRE: + return left.next_fire - right.next_fire; + case SubsystemSortBy.TICK_USAGE: + return left.tick_usage - right.tick_usage; + case SubsystemSortBy.TICK_OVERRUN: + return left.tick_overrun - right.tick_overrun; + case SubsystemSortBy.COST: + return left.cost_ms - right.cost_ms; + } + }); + if (!asending) { + sorted.reverse(); + } + return sorted; +}; + +export const ControllerOverview = () => { + const { act, data } = useBackend(); + const { world_time, map_cpu, subsystems, fast_update } = data; + + const [filterName, setFilterName] = useState(''); + const [sortBy, setSortBy] = useState(SubsystemSortBy.NAME); + const [sortAscending, setSortAscending] = useState(true); + + let filteredSubsystems = useMemo(() => { + if (!filterName) { + return subsystems; + } + + return subsystems.filter(() => + createSearch(filterName, (subsystem: SubsystemData) => subsystem.name), + ); + }, [filterName, subsystems]); + + let sortedSubsystems = useMemo(() => { + return sortSubsystemBy(filteredSubsystems, sortBy, sortAscending); + }, [sortBy, sortAscending, filteredSubsystems]); + + const overallUsage = subsystems.reduce( + (acc, subsystem) => acc + subsystem.tick_usage, + 0, + ); + const overallOverrun = subsystems.reduce( + (acc, subsystem) => acc + subsystem.tick_overrun, + 0, + ); + + return ( + + +
    + + World Time: {world_time} + Map CPU: {map_cpu.toFixed(2)}% + + Overall Usage: {(overallUsage * 0.01).toFixed(2)}% + + + Overall Overrun: {(overallOverrun * 0.01).toFixed(2)}% + + +
    +
    { + act('toggle_fast_update'); + }} + /> + } + > + setFilterName(value)} + /> + + + + + + +
    +
    + + {sortedSubsystems.map((subsystem) => ( + + ))} + +
    +
    +
    + ); +}; diff --git a/tgui/packages/tgui/interfaces/CrewConsole.jsx b/tgui/packages/tgui/interfaces/CrewConsole.jsx index 8ed7efa5c11..ef3f8c31a38 100644 --- a/tgui/packages/tgui/interfaces/CrewConsole.jsx +++ b/tgui/packages/tgui/interfaces/CrewConsole.jsx @@ -86,7 +86,7 @@ export const CrewConsole = () => { const CrewTable = (props) => { const { act, data } = useBackend(); - const sensors = sortBy((s) => s.ijob)(data.sensors ?? []); + const sensors = sortBy(data.sensors ?? [], (s) => s.ijob); return ( diff --git a/tgui/packages/tgui/interfaces/DestinationTagger.tsx b/tgui/packages/tgui/interfaces/DestinationTagger.tsx index b1acfe192a7..5326f93e01b 100644 --- a/tgui/packages/tgui/interfaces/DestinationTagger.tsx +++ b/tgui/packages/tgui/interfaces/DestinationTagger.tsx @@ -1,5 +1,4 @@ import { map, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { useBackend } from '../backend'; import { Button, Section, Stack } from '../components'; @@ -25,13 +24,17 @@ type DestinationInfo = { * @returns The alphetically sorted list of destinations. */ const sortDestinations = (locations: string[]): DestinationInfo[] => { - return flow([ - map((name, index) => ({ - name: name.toUpperCase(), - sorting_id: index + 1, - })), - sortBy((dest) => dest.name), - ])(locations); + return sortBy( + map( + locations, + (name, index) => + ({ + name: name.toUpperCase(), + sorting_id: index + 1, + }) as DestinationInfo, + ), + (dest) => dest.name, + ); }; export const DestinationTagger = (props) => { diff --git a/tgui/packages/tgui/interfaces/DnaConsole/DnaConsoleStorage.jsx b/tgui/packages/tgui/interfaces/DnaConsole/DnaConsoleStorage.jsx index 43c22b321a0..681b4f211d7 100644 --- a/tgui/packages/tgui/interfaces/DnaConsole/DnaConsoleStorage.jsx +++ b/tgui/packages/tgui/interfaces/DnaConsole/DnaConsoleStorage.jsx @@ -211,7 +211,7 @@ const StorageButtons = (props) => { const StorageChromosomes = (props) => { const { data, act } = useBackend(); const chromos = data.chromoStorage ?? []; - const uniqueChromos = uniqBy((chromo) => chromo.Name)(chromos); + const uniqueChromos = uniqBy(chromos, (chromo) => chromo.Name); const chromoName = data.view.storageChromoName; const chromo = chromos.find((chromo) => chromo.Name === chromoName); diff --git a/tgui/packages/tgui/interfaces/DnaConsole/MutationInfo.jsx b/tgui/packages/tgui/interfaces/DnaConsole/MutationInfo.jsx index 89a1468d953..2629a029fa8 100644 --- a/tgui/packages/tgui/interfaces/DnaConsole/MutationInfo.jsx +++ b/tgui/packages/tgui/interfaces/DnaConsole/MutationInfo.jsx @@ -1,5 +1,4 @@ import { filter, uniqBy } from 'common/collections'; -import { flow } from 'common/fp'; import { useBackend } from '../../backend'; import { @@ -122,10 +121,10 @@ export const MutationInfo = (props) => { isSameMutation(x, mutation), ); const savedToDisk = diskMutations.find((x) => isSameMutation(x, mutation)); - const combinedMutations = flow([ - uniqBy((mutation) => mutation.Name), - filter((x) => x.Name !== mutation.Name), - ])([...diskMutations, ...mutationStorage]); + const combinedMutations = filter( + uniqBy([...diskMutations, ...mutationStorage], (mutation) => mutation.Name), + (x) => x.Name !== mutation.Name, + ); return ( <> diff --git a/tgui/packages/tgui/interfaces/DnaVault.jsx b/tgui/packages/tgui/interfaces/DnaVault.tsx similarity index 75% rename from tgui/packages/tgui/interfaces/DnaVault.jsx rename to tgui/packages/tgui/interfaces/DnaVault.tsx index 5ac7711412d..2b6781d6cf7 100644 --- a/tgui/packages/tgui/interfaces/DnaVault.jsx +++ b/tgui/packages/tgui/interfaces/DnaVault.tsx @@ -1,28 +1,44 @@ +import { BooleanLike } from 'common/react'; + import { useBackend } from '../backend'; import { Box, Button, - Grid, LabeledList, ProgressBar, Section, + Stack, } from '../components'; import { Window } from '../layouts'; -export const DnaVault = (props) => { - const { act, data } = useBackend(); +type Data = { + animals_max: number; + animals: number; + choiceA: string; + choiceB: string; + completed: BooleanLike; + dna_max: number; + dna: number; + plants_max: number; + plants: number; + used: BooleanLike; +}; + +export function DnaVault(props) { + const { act, data } = useBackend(); const { - completed, - used, + animals_max, + animals, choiceA, choiceB, - dna, + completed, dna_max, - plants, + dna, plants_max, - animals, - animals_max, + plants, + used, } = data; + return ( @@ -50,37 +66,39 @@ export const DnaVault = (props) => { Applicable Gene Therapy Treatments - - + + + + + + )} ); -}; +} diff --git a/tgui/packages/tgui/interfaces/EightBallVote.tsx b/tgui/packages/tgui/interfaces/EightBallVote.tsx index 30ab7baae48..f85b8724ffe 100644 --- a/tgui/packages/tgui/interfaces/EightBallVote.tsx +++ b/tgui/packages/tgui/interfaces/EightBallVote.tsx @@ -2,50 +2,51 @@ import { BooleanLike } from 'common/react'; import { toTitleCase } from 'common/string'; import { useBackend } from '../backend'; -import { Box, Button, Grid, NoticeBox, Section } from '../components'; +import { Box, Button, NoticeBox, Section, Stack } from '../components'; import { Window } from '../layouts'; type Data = { - shaking: BooleanLike; - question: string; answers: Answer[]; + question: string; + shaking: BooleanLike; }; type Answer = { - answer: string; amount: number; + answer: string; selected: BooleanLike; }; -export const EightBallVote = (props) => { - const { act, data } = useBackend(); +export function EightBallVote(props) { + const { data } = useBackend(); const { shaking } = data; + return ( - {(!shaking && ( + {(shaking && ( No question is currently being asked. )) || } ); -}; +} -const EightBallVoteQuestion = (props) => { +function EightBallVoteQuestion(props) { const { act, data } = useBackend(); const { question, answers = [] } = data; + return (
    "{question}" - + {answers.map((answer) => ( - + {answer.amount} - + ))} - +
    ); -}; +} diff --git a/tgui/packages/tgui/interfaces/EmergencyShuttleConsole.jsx b/tgui/packages/tgui/interfaces/EmergencyShuttleConsole.tsx similarity index 73% rename from tgui/packages/tgui/interfaces/EmergencyShuttleConsole.jsx rename to tgui/packages/tgui/interfaces/EmergencyShuttleConsole.tsx index b7b09bdca6a..04214e092d6 100644 --- a/tgui/packages/tgui/interfaces/EmergencyShuttleConsole.jsx +++ b/tgui/packages/tgui/interfaces/EmergencyShuttleConsole.tsx @@ -1,17 +1,34 @@ +import { BooleanLike } from 'common/react'; + import { useBackend } from '../backend'; -import { Box, Button, Grid, Section } from '../components'; +import { Box, Button, Section, Stack } from '../components'; import { Window } from '../layouts'; -export const EmergencyShuttleConsole = (props) => { - const { act, data } = useBackend(); +type Data = { + authorizations_remaining: number; + authorizations: Authorization[]; + emagged: BooleanLike; + enabled: BooleanLike; + engines_started: BooleanLike; + timer_str: string; +}; + +type Authorization = { + job: string; + name: string; +}; + +export function EmergencyShuttleConsole(props) { + const { act, data } = useBackend(); const { - timer_str, - enabled, - emagged, - engines_started, - authorizations_remaining, authorizations = [], + authorizations_remaining, + emagged, + enabled, + engines_started, + timer_str, } = data; + return ( @@ -29,41 +46,42 @@ export const EmergencyShuttleConsole = (props) => {
    act('abort')} - /> + > + Repeal All + } > - - + + + + + +
    @@ -71,7 +89,11 @@ export const EmergencyShuttleConsole = (props) => { } > - {authorizations.length > 0 ? ( + {authorizations.length === 0 ? ( + + No Active Authorizations + + ) : ( authorizations.map((authorization) => ( { {authorization.name} ({authorization.job}) )) - ) : ( - - No Active Authorizations - )}
    @@ -93,4 +111,4 @@ export const EmergencyShuttleConsole = (props) => {
    ); -}; +} diff --git a/tgui/packages/tgui/interfaces/ExperimentConfigure.jsx b/tgui/packages/tgui/interfaces/ExperimentConfigure.jsx index 0c632afd283..d91bc564e44 100644 --- a/tgui/packages/tgui/interfaces/ExperimentConfigure.jsx +++ b/tgui/packages/tgui/interfaces/ExperimentConfigure.jsx @@ -109,7 +109,7 @@ export const ExperimentConfigure = (props) => { const { always_active, has_start_callback } = data; let techwebs = data.techwebs ?? []; - const experiments = sortBy((exp) => exp.name)(data.experiments ?? []); + const experiments = sortBy(data.experiments ?? [], (exp) => exp.name); // Group servers together by web let webs = new Map(); diff --git a/tgui/packages/tgui/interfaces/Fabrication/DesignBrowser.tsx b/tgui/packages/tgui/interfaces/Fabrication/DesignBrowser.tsx index af5bddf4d5b..e4951bd0041 100644 --- a/tgui/packages/tgui/interfaces/Fabrication/DesignBrowser.tsx +++ b/tgui/packages/tgui/interfaces/Fabrication/DesignBrowser.tsx @@ -229,8 +229,9 @@ export const DesignBrowser = ( - {sortBy((category: Category) => category.title)( + {sortBy( Object.values(root.subcategories), + (category: Category) => category.title, ).map((category) => ( (
    {searchText.length > 0 ? ( - {sortBy((design: T) => design.name)( + {sortBy( Object.values(root.descendants), + (design: T) => design.name, ) .filter((design) => design.name @@ -290,8 +292,9 @@ export const DesignBrowser = ( ) : selectedCategory === ALL_CATEGORY ? ( - {sortBy((design: T) => design.name)( + {sortBy( Object.values(root.descendants), + (design: T) => design.name, ).map((design) => buildRecipeElement( design, @@ -380,8 +383,9 @@ const DesignBrowserTab = ( Object.entries(category.subcategories).length > 0 && selectedCategory === category.title && (
    - {sortBy((category: Category) => category.title)( + {sortBy( Object.values(category.subcategories), + (category: Category) => category.title, ).map((subcategory) => ( ( const body = ( - {sortBy((design: T) => design.name)(category.children).map((design) => + {sortBy(category.children, (design: T) => design.name).map((design) => buildRecipeElement( design, availableMaterials || {}, diff --git a/tgui/packages/tgui/interfaces/Fabrication/MaterialAccessBar.tsx b/tgui/packages/tgui/interfaces/Fabrication/MaterialAccessBar.tsx index 2936d93df3f..83923d5bd48 100644 --- a/tgui/packages/tgui/interfaces/Fabrication/MaterialAccessBar.tsx +++ b/tgui/packages/tgui/interfaces/Fabrication/MaterialAccessBar.tsx @@ -55,7 +55,7 @@ export const MaterialAccessBar = (props: MaterialAccessBarProps) => { return ( - {sortBy((m: Material) => MATERIAL_RARITY[m.name])(availableMaterials).map( + {sortBy(availableMaterials, (m: Material) => MATERIAL_RARITY[m.name]).map( (material) => ( { const { act } = useBackend(); const { data } = useBackend(); const faxes = data.faxes - ? sortBy((sortFax: FaxInfo) => sortFax.fax_name)( + ? sortBy( data.syndicate_network ? data.faxes.filter((filterFax: FaxInfo) => filterFax.visible) : data.faxes.filter( (filterFax: FaxInfo) => filterFax.visible && !filterFax.syndicate_network, ), + (sortFax: FaxInfo) => sortFax.fax_name, ) : []; return ( diff --git a/tgui/packages/tgui/interfaces/Filteriffic.jsx b/tgui/packages/tgui/interfaces/Filteriffic.jsx index b13cddc34f4..09bd1426452 100644 --- a/tgui/packages/tgui/interfaces/Filteriffic.jsx +++ b/tgui/packages/tgui/interfaces/Filteriffic.jsx @@ -155,10 +155,9 @@ const FilterFlagsEntry = (props) => { const filterInfo = data.filter_info; const flags = filterInfo[filterType]['flags']; - return map((bitField, flagName) => ( + return map(flags, (bitField, flagName) => ( act('modify_filter_value', { name: filterName, @@ -167,8 +166,11 @@ const FilterFlagsEntry = (props) => { }, }) } - /> - ))(flags); + key={flagName} + > + {flagName} + + )); }; const FilterDataEntry = (props) => { @@ -340,9 +342,9 @@ export const Filteriffic = (props) => { {!hasFilters ? ( No filters ) : ( - map((entry, key) => ( + map(filters, (entry, key) => ( - ))(filters) + )) )}
    diff --git a/tgui/packages/tgui/interfaces/FishCatalog.tsx b/tgui/packages/tgui/interfaces/FishCatalog.tsx index 01efc5e3531..7bb85054fb0 100644 --- a/tgui/packages/tgui/interfaces/FishCatalog.tsx +++ b/tgui/packages/tgui/interfaces/FishCatalog.tsx @@ -1,5 +1,4 @@ import { sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { classes } from 'common/react'; import { capitalize } from 'common/string'; import { useState } from 'react'; @@ -38,9 +37,7 @@ type FishCatalogData = { export const FishCatalog = (props) => { const { act, data } = useBackend(); const { fish_info, sponsored_by } = data; - const fish_by_name = flow([sortBy((fish: FishInfo) => fish.name)])( - fish_info || [], - ); + const fish_by_name = sortBy(fish_info || [], (fish: FishInfo) => fish.name); const [currentFish, setCurrentFish] = useState(null); return ( diff --git a/tgui/packages/tgui/interfaces/Gps.jsx b/tgui/packages/tgui/interfaces/Gps.jsx index 662335fcdc3..c12ba6a9efd 100644 --- a/tgui/packages/tgui/interfaces/Gps.jsx +++ b/tgui/packages/tgui/interfaces/Gps.jsx @@ -7,30 +7,36 @@ import { useBackend } from '../backend'; import { Box, Button, Icon, LabeledList, Section, Table } from '../components'; import { Window } from '../layouts'; -const coordsToVec = (coords) => map(parseFloat)(coords.split(', ')); +const coordsToVec = (coords) => map(coords.split(', '), parseFloat); export const Gps = (props) => { const { act, data } = useBackend(); const { currentArea, currentCoords, globalmode, power, tag, updating } = data; const signals = flow([ - map((signal, index) => { - // Calculate distance to the target. BYOND distance is capped to 127, - // that's why we roll our own calculations here. - const dist = - signal.dist && - Math.round( - vecLength( - vecSubtract(coordsToVec(currentCoords), coordsToVec(signal.coords)), - ), - ); - return { ...signal, dist, index }; - }), - sortBy( - // Signals with distance metric go first - (signal) => signal.dist === undefined, - // Sort alphabetically - (signal) => signal.entrytag, - ), + (signals) => + map(signals, (signal, index) => { + // Calculate distance to the target. BYOND distance is capped to 127, + // that's why we roll our own calculations here. + const dist = + signal.dist && + Math.round( + vecLength( + vecSubtract( + coordsToVec(currentCoords), + coordsToVec(signal.coords), + ), + ), + ); + return { ...signal, dist, index }; + }), + (signals) => + sortBy( + signals, + // Signals with distance metric go first + (signal) => signal.dist === undefined, + // Sort alphabetically + (signal) => signal.entrytag, + ), ])(data.signals || []); return ( diff --git a/tgui/packages/tgui/interfaces/Hypertorus/Gases.tsx b/tgui/packages/tgui/interfaces/Hypertorus/Gases.tsx index 8482bd665ec..74457a365bb 100644 --- a/tgui/packages/tgui/interfaces/Hypertorus/Gases.tsx +++ b/tgui/packages/tgui/interfaces/Hypertorus/Gases.tsx @@ -1,5 +1,4 @@ import { filter, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { toFixed } from 'common/math'; import { useBackend } from 'tgui/backend'; import { @@ -90,10 +89,10 @@ const GasList = (props: GasListProps) => { } = props; const { start_power, start_cooling } = data; - const gases: HypertorusGas[] = flow([ - filter((gas: HypertorusGas) => gas.amount >= 0.01), - sortBy((gas: HypertorusGas) => -gas.amount), - ])(raw_gases); + const gases: HypertorusGas[] = sortBy( + filter(raw_gases, (gas) => gas.amount >= 0.01), + (gas) => -gas.amount, + ); if (stickyGases) { ensure_gases(gases, stickyGases); diff --git a/tgui/packages/tgui/interfaces/Jukebox.tsx b/tgui/packages/tgui/interfaces/Jukebox.tsx index 073b97ddee1..f450b08ebc4 100644 --- a/tgui/packages/tgui/interfaces/Jukebox.tsx +++ b/tgui/packages/tgui/interfaces/Jukebox.tsx @@ -1,5 +1,4 @@ import { sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { BooleanLike } from '../../common/react'; import { useBackend } from '../backend'; @@ -32,7 +31,7 @@ export const Jukebox = () => { const { act, data } = useBackend(); const { active, looping, track_selected, volume, songs } = data; - const songs_sorted: Song[] = flow([sortBy((song: Song) => song.name)])(songs); + const songs_sorted: Song[] = sortBy(songs, (song: Song) => song.name); const song_selected: Song | undefined = songs.find( (song) => song.name === track_selected, ); diff --git a/tgui/packages/tgui/interfaces/LaborClaimConsole.jsx b/tgui/packages/tgui/interfaces/LaborClaimConsole.jsx index 27b3cc0e05f..4e0aebdcdd5 100644 --- a/tgui/packages/tgui/interfaces/LaborClaimConsole.jsx +++ b/tgui/packages/tgui/interfaces/LaborClaimConsole.jsx @@ -35,25 +35,14 @@ export const LaborClaimConsole = (props) => {
    -
    -
    - - Material - - Value - - - {ores.map((ore) => ( - - {toTitleCase(ore.ore)} - - - {ore.value} - - - - ))} -
    +
    + The nearby stacking machine will unload crates and collect smelted + materials, points will be calculated based on volume of delivered + materials. +
    + Please note that only sheets printed with our manufacturer's seal of + quality, such as those produced from the work camp furnace, will be + accepted as proof of labour.
    diff --git a/tgui/packages/tgui/interfaces/LaunchpadConsole.jsx b/tgui/packages/tgui/interfaces/LaunchpadConsole.jsx deleted file mode 100644 index c3145844fc2..00000000000 --- a/tgui/packages/tgui/interfaces/LaunchpadConsole.jsx +++ /dev/null @@ -1,276 +0,0 @@ -import { useBackend } from '../backend'; -import { - Box, - Button, - Divider, - Flex, - Grid, - Input, - NoticeBox, - NumberInput, - Section, -} from '../components'; -import { Window } from '../layouts'; - -const LaunchpadButtonPad = (props) => { - const { act } = useBackend(); - return ( - - -
    - ); -}; - -export const LaunchpadConsole = (props) => { - const { act, data } = useBackend(); - const { launchpads = [], selected_id } = data; - return ( - - - {(launchpads.length === 0 && ( - No Pads Connected - )) || ( -
    - - - {launchpads.map((launchpad) => ( -
    - )} -
    -
    - ); -}; diff --git a/tgui/packages/tgui/interfaces/LaunchpadConsole.tsx b/tgui/packages/tgui/interfaces/LaunchpadConsole.tsx new file mode 100644 index 00000000000..fdad9955894 --- /dev/null +++ b/tgui/packages/tgui/interfaces/LaunchpadConsole.tsx @@ -0,0 +1,259 @@ +import { useBackend } from '../backend'; +import { + Box, + Button, + Icon, + Input, + NoticeBox, + NumberInput, + Section, + Stack, + Tabs, +} from '../components'; +import { Window } from '../layouts'; + +type Data = { + launchpads: LaunchPad[]; + pad_active: number; + pad_name: string; + range: number; + selected_id: number; + selected_pad: string; + x: number; + y: number; +}; + +type LaunchPad = { + id: number; + name: string; +}; + +const buttonConfigs = [ + [ + { icon: 'arrow-left', iconRotation: 45, x: -1, y: 1 }, + { icon: 'arrow-left', x: -1 }, + { icon: 'arrow-down', iconRotation: 45, x: -1, y: -1 }, + ], + [ + { icon: 'arrow-up', y: 1 }, + { text: 'R', x: 0, y: 0 }, + { icon: 'arrow-down', y: -1 }, + ], + [ + { icon: 'arrow-up', iconRotation: 45, x: 1, y: 1 }, + { icon: 'arrow-right', x: 1 }, + { icon: 'arrow-right', iconRotation: 45, x: 1, y: -1 }, + ], +] as const; + +export function LaunchpadConsole(props) { + const { data } = useBackend(); + const { launchpads = [], selected_id } = data; + + return ( + + + {launchpads.length === 0 ? ( + No Pads Connected + ) : ( + + + + + + + {!selected_id ? ( + Please select a pad + ) : ( + + )} + + + )} + + + ); +} + +export function LaunchpadControl(props) { + return ( + + + + + +
    + + + + + + + + +
    +
    + + + +
    + ); +} + +function LaunchpadTabs(props) { + const { act, data } = useBackend(); + const { launchpads = [], selected_id } = data; + + return ( +
    + + {launchpads.map((pad) => ( + + act('select_pad', { + id: pad.id, + }) + } + > + {pad.name} + + ))} + +
    + ); +} + +function LaunchpadTitle(props) { + const { act, data } = useBackend(); + const { pad_name } = data; + + return ( +
    + + + + act('rename', { + name: value, + }) + } + /> + + + + + +
    + ); +} + +function LaunchpadButtonPad(props) { + const { act } = useBackend(); + + return ( +
    + + {buttonConfigs.map((buttonRow, i) => ( + + {buttonRow.map((buttonConfig, j) => ( + + ))} + + ))} + +
    + ); +} + +function TargetingControls(props) { + const { act, data } = useBackend(); + const { x, y, range } = data; + + const inputConfigs = [ + { value: x, axis: 'x', icon: 'arrows-alt-h' }, + { value: y, axis: 'y', icon: 'arrows-alt-v' }, + ]; + + return ( +
    + {inputConfigs.map((inputConfig, i) => ( + + + + {inputConfig.axis.toUpperCase()} + + + + + act('set_pos', { + [inputConfig.axis]: value, + }) + } + step={1} + stepPixelSize={10} + value={inputConfig.value} + width="90px" + /> + + + ))} +
    + ); +} + +function DeliveryButtons(props) { + const { act } = useBackend(); + + return ( +
    + + + + + + + + +
    + ); +} diff --git a/tgui/packages/tgui/interfaces/LibraryAdmin.tsx b/tgui/packages/tgui/interfaces/LibraryAdmin.tsx index f805a46c7fb..fd88fdc48fb 100644 --- a/tgui/packages/tgui/interfaces/LibraryAdmin.tsx +++ b/tgui/packages/tgui/interfaces/LibraryAdmin.tsx @@ -1,5 +1,4 @@ import { map, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { capitalize } from 'common/string'; import { useState } from 'react'; @@ -81,10 +80,14 @@ type Book = { category: string; title: string; id: number; +}; + +type AdminBook = Book & { + author_ckey: string; deleted: boolean; }; -type DisplayBook = Book & { +type DisplayAdminBook = AdminBook & { key: number; }; @@ -120,14 +123,18 @@ const SearchAndDisplay = (props) => { view_raw, show_deleted, } = data; - const books = flow([ - map((book, i) => ({ - ...book, - // Generate a unique id - key: i, - })), - sortBy((book) => book.key), - ])(pages); + const books = sortBy( + map( + pages, + (book, i) => + ({ + ...book, + // Generate a unique id + key: i, + }) as DisplayAdminBook, + ), + (book) => book.key, + ); return (
    diff --git a/tgui/packages/tgui/interfaces/LibraryConsole.jsx b/tgui/packages/tgui/interfaces/LibraryConsole.jsx index 83d034915b8..386ac3ca0c0 100644 --- a/tgui/packages/tgui/interfaces/LibraryConsole.jsx +++ b/tgui/packages/tgui/interfaces/LibraryConsole.jsx @@ -1,5 +1,4 @@ import { map, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { classes } from 'common/react'; import { useState } from 'react'; @@ -136,14 +135,14 @@ export const Inventory = (props) => { export const InventoryDetails = (props) => { const { act, data } = useBackend(); - const inventory = flow([ - map((book, i) => ({ + const inventory = sortBy( + map(data.inventory, (book, i) => ({ ...book, // Generate a unique id key: i, })), - sortBy((book) => book.key), - ])(data.inventory); + (book) => book.key, + ); return (
    @@ -261,14 +260,14 @@ export const CheckoutEntries = (props) => { const CheckoutModal = (props) => { const { act, data } = useBackend(); - const inventory = flow([ - map((book, i) => ({ + const inventory = sortBy( + map(data.inventory, (book, i) => ({ ...book, // Generate a unique id key: i, })), - sortBy((book) => book.key), - ])(data.inventory); + (book) => book.key, + ); const [checkoutBook, setCheckoutBook] = useLocalState('CheckoutBook', false); const [bookName, setBookName] = useState('Insert Book name...'); @@ -387,14 +386,14 @@ export const SearchAndDisplay = (props) => { params_changed, can_db_request, } = data; - const records = flow([ - map((record, i) => ({ + const records = sortBy( + map(data.pages, (record, i) => ({ ...record, // Generate a unique id key: i, })), - sortBy((record) => record.key), - ])(data.pages); + (record) => record.key, + ); return ( diff --git a/tgui/packages/tgui/interfaces/LibraryVisitor.jsx b/tgui/packages/tgui/interfaces/LibraryVisitor.jsx index 6b8edb380be..cb27e42704d 100644 --- a/tgui/packages/tgui/interfaces/LibraryVisitor.jsx +++ b/tgui/packages/tgui/interfaces/LibraryVisitor.jsx @@ -1,5 +1,4 @@ import { map, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { useBackend } from '../backend'; import { @@ -71,14 +70,14 @@ const SearchAndDisplay = (props) => { author, params_changed, } = data; - const records = flow([ - map((record, i) => ({ + const records = sortBy( + map(data.pages, (record, i) => ({ ...record, // Generate a unique id key: i, })), - sortBy((record) => record.key), - ])(data.pages); + (record) => record.key, + ); return (
    diff --git a/tgui/packages/tgui/interfaces/LootPanel/GroupedContents.tsx b/tgui/packages/tgui/interfaces/LootPanel/GroupedContents.tsx new file mode 100644 index 00000000000..5bfecce0b8a --- /dev/null +++ b/tgui/packages/tgui/interfaces/LootPanel/GroupedContents.tsx @@ -0,0 +1,47 @@ +import { createSearch } from 'common/string'; +import { useMemo } from 'react'; + +import { Flex } from '../../components'; +import { LootBox } from './LootBox'; +import { SearchGroup, SearchItem } from './types'; + +type Props = { + contents: SearchItem[]; + searchText: string; +}; + +export function GroupedContents(props: Props) { + const { contents, searchText } = props; + + // limitations: items with different stack counts, charges etc. + const contentsByPath = useMemo(() => { + const acc: Record = {}; + + for (let i = 0; i < contents.length; i++) { + const item = contents[i]; + if (item.path) { + if (!acc[item.path]) { + acc[item.path] = []; + } + acc[item.path].push(item); + } else { + acc[item.ref] = [item]; + } + } + return acc; + }, [contents]); + + const filteredContents: SearchGroup[] = Object.entries(contentsByPath) + .filter(createSearch(searchText, ([_, items]) => items[0].name)) + .map(([_, items]) => ({ amount: items.length, item: items[0] })); + + return ( + + {filteredContents.map((group) => ( + + + + ))} + + ); +} diff --git a/tgui/packages/tgui/interfaces/LootPanel/IconDisplay.tsx b/tgui/packages/tgui/interfaces/LootPanel/IconDisplay.tsx new file mode 100644 index 00000000000..889d50de884 --- /dev/null +++ b/tgui/packages/tgui/interfaces/LootPanel/IconDisplay.tsx @@ -0,0 +1,24 @@ +import { DmIcon, Icon, Image } from '../../components'; +import { SearchItem } from './types'; + +type Props = { + item: SearchItem; +}; + +export function IconDisplay(props: Props) { + const { + item: { icon, icon_state }, + } = props; + + const fallback = ; + + if (!icon) { + return fallback; + } + + if (icon_state) { + return ; + } + + return ; +} diff --git a/tgui/packages/tgui/interfaces/LootPanel/LootBox.tsx b/tgui/packages/tgui/interfaces/LootPanel/LootBox.tsx new file mode 100644 index 00000000000..22b0c8532dd --- /dev/null +++ b/tgui/packages/tgui/interfaces/LootPanel/LootBox.tsx @@ -0,0 +1,53 @@ +import { capitalizeAll } from 'common/string'; + +import { useBackend } from '../../backend'; +import { Tooltip } from '../../components'; +import { IconDisplay } from './IconDisplay'; +import { SearchGroup, SearchItem } from './types'; + +type Props = + | { + item: SearchItem; + } + | { + group: SearchGroup; + }; + +export function LootBox(props: Props) { + const { act } = useBackend(); + + let amount = 0; + let item: SearchItem; + if ('group' in props) { + amount = props.group.amount; + item = props.group.item; + } else { + item = props.item; + } + + return ( + +
    + act('grab', { + ctrl: event.ctrlKey, + ref: item.ref, + shift: event.shiftKey, + }) + } + onContextMenu={(event) => { + event.preventDefault(); + act('grab', { + middle: true, + ref: item.ref, + shift: true, + }); + }} + > + + {amount > 1 &&
    {amount}
    } +
    +
    + ); +} diff --git a/tgui/packages/tgui/interfaces/LootPanel/RawContents.tsx b/tgui/packages/tgui/interfaces/LootPanel/RawContents.tsx new file mode 100644 index 00000000000..4241d36dc0a --- /dev/null +++ b/tgui/packages/tgui/interfaces/LootPanel/RawContents.tsx @@ -0,0 +1,28 @@ +import { createSearch } from 'common/string'; + +import { Flex } from '../../components'; +import { LootBox } from './LootBox'; +import { SearchItem } from './types'; + +type Props = { + contents: SearchItem[]; + searchText: string; +}; + +export function RawContents(props: Props) { + const { contents, searchText } = props; + + const filteredContents = contents.filter( + createSearch(searchText, (item: SearchItem) => item.name), + ); + + return ( + + {filteredContents.map((item) => ( + + + + ))} + + ); +} diff --git a/tgui/packages/tgui/interfaces/LootPanel/index.tsx b/tgui/packages/tgui/interfaces/LootPanel/index.tsx new file mode 100644 index 00000000000..bd64113f302 --- /dev/null +++ b/tgui/packages/tgui/interfaces/LootPanel/index.tsx @@ -0,0 +1,76 @@ +import { KEY } from 'common/keys'; +import { BooleanLike } from 'common/react'; +import { useState } from 'react'; + +import { useBackend } from '../../backend'; +import { Button, Input, Section, Stack } from '../../components'; +import { Window } from '../../layouts'; +import { GroupedContents } from './GroupedContents'; +import { RawContents } from './RawContents'; +import { SearchItem } from './types'; + +type Data = { + contents: SearchItem[]; + searching: BooleanLike; +}; + +export function LootPanel(props) { + const { act, data } = useBackend(); + const { contents = [], searching } = data; + + const [grouping, setGrouping] = useState(true); + const [searchText, setSearchText] = useState(''); + + const total = contents.length ? contents.length - 1 : 0; + + return ( + + { + if (event.key === KEY.Escape) { + Byond.sendMessage('close'); + } + }} + > +
    + + setSearchText(value)} + placeholder="Search" + /> + + +
    +
    +
    + ); +} diff --git a/tgui/packages/tgui/interfaces/LootPanel/types.ts b/tgui/packages/tgui/interfaces/LootPanel/types.ts new file mode 100644 index 00000000000..f17b02b0c13 --- /dev/null +++ b/tgui/packages/tgui/interfaces/LootPanel/types.ts @@ -0,0 +1,13 @@ +export type SearchItem = { + name: string; + path: string; + ref: string; +} & Partial<{ + icon: string; + icon_state: string; +}>; + +export type SearchGroup = { + amount: number; + item: SearchItem; +}; diff --git a/tgui/packages/tgui/interfaces/MatMarket.tsx b/tgui/packages/tgui/interfaces/MatMarket.tsx index 11de67fb656..d793b8501f0 100644 --- a/tgui/packages/tgui/interfaces/MatMarket.tsx +++ b/tgui/packages/tgui/interfaces/MatMarket.tsx @@ -118,7 +118,7 @@ export const MatMarket = (props) => {
    - {sortBy((tempmat: Material) => tempmat.rarity)(materials).map( + {sortBy(materials, (tempmat: Material) => tempmat.rarity).map( (material, i) => (
    diff --git a/tgui/packages/tgui/interfaces/Mecha/data.ts b/tgui/packages/tgui/interfaces/Mecha/data.ts index 993c7a1d4be..0bccc7fa5c1 100644 --- a/tgui/packages/tgui/interfaces/Mecha/data.ts +++ b/tgui/packages/tgui/interfaces/Mecha/data.ts @@ -1,5 +1,7 @@ import { BooleanLike } from 'common/react'; +import { Region } from '../common/AccessConfig'; + export type AccessData = { name: string; number: number; @@ -25,7 +27,7 @@ export type MainData = { overclock_temp_percentage: number; one_access: BooleanLike; - regions: string[]; + regions: Region[]; accesses: string[]; servo_rating: number; diff --git a/tgui/packages/tgui/interfaces/MedicalRecords/RecordTabs.tsx b/tgui/packages/tgui/interfaces/MedicalRecords/RecordTabs.tsx index 7aee1f276a8..03672e05008 100644 --- a/tgui/packages/tgui/interfaces/MedicalRecords/RecordTabs.tsx +++ b/tgui/packages/tgui/interfaces/MedicalRecords/RecordTabs.tsx @@ -1,5 +1,4 @@ import { filter, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { useState } from 'react'; import { useBackend, useLocalState } from 'tgui/backend'; import { @@ -28,10 +27,10 @@ export const MedicalRecordTabs = (props) => { const [search, setSearch] = useState(''); - const sorted: MedicalRecord[] = flow([ - filter((record: MedicalRecord) => isRecordMatch(record, search)), - sortBy((record: MedicalRecord) => record.name?.toLowerCase()), - ])(records); + const sorted: MedicalRecord[] = sortBy( + filter(records, (record) => isRecordMatch(record, search)), + (record) => record.name?.toLowerCase(), + ); return ( diff --git a/tgui/packages/tgui/interfaces/NtosArcade.jsx b/tgui/packages/tgui/interfaces/NtosArcade.jsx deleted file mode 100644 index b8c9aa05109..00000000000 --- a/tgui/packages/tgui/interfaces/NtosArcade.jsx +++ /dev/null @@ -1,135 +0,0 @@ -import { resolveAsset } from '../assets'; -import { useBackend } from '../backend'; -import { - AnimatedNumber, - Box, - Button, - Grid, - LabeledList, - ProgressBar, - Section, -} from '../components'; -import { NtosWindow } from '../layouts'; - -export const NtosArcade = (props) => { - const { act, data } = useBackend(); - return ( - - -
    - - - - - - - - {data.PlayerHitpoints}HP - - - - - {data.PlayerMP}MP - - - - -
    - {data.Status} -
    -
    - - - - HP - - -
    - -
    -
    -
    - -
    -
    -
    - ); -}; diff --git a/tgui/packages/tgui/interfaces/NtosArcade.tsx b/tgui/packages/tgui/interfaces/NtosArcade.tsx new file mode 100644 index 00000000000..ea63e62e037 --- /dev/null +++ b/tgui/packages/tgui/interfaces/NtosArcade.tsx @@ -0,0 +1,178 @@ +import { BooleanLike } from 'common/react'; + +import { resolveAsset } from '../assets'; +import { useBackend } from '../backend'; +import { + AnimatedNumber, + Box, + Button, + Divider, + LabeledList, + NoticeBox, + ProgressBar, + Section, + Stack, +} from '../components'; +import { NtosWindow } from '../layouts'; + +type Data = { + BossID: string; + GameActive: BooleanLike; + Hitpoints: number; + PauseState: BooleanLike; + PlayerHitpoints: number; + PlayerMP: number; + Status: string; + TicketCount: number; +}; + +export function NtosArcade(props) { + return ( + + +
    + + + + + + + + + +
    +
    +
    + ); +} + +function PlayerStats(props) { + const { data } = useBackend(); + const { PauseState, PlayerHitpoints, PlayerMP, Status } = data; + + return ( + <> + + + + {PlayerHitpoints}HP + + + + + {PlayerMP}MP + + + + + {Status} + + ); +} + +function BossBar(props) { + const { data } = useBackend(); + const { BossID, Hitpoints } = data; + + return ( + <> + + + HP + + +
    + +
    + + ); +} + +function BottomButtons(props) { + const { act, data } = useBackend(); + const { GameActive, PauseState, TicketCount } = data; + + return ( + <> + + + + + + + + + = 1 ? 'good' : 'normal'}> + Earned Tickets: {TicketCount} + + + ); +} diff --git a/tgui/packages/tgui/interfaces/NtosCrewManifest.jsx b/tgui/packages/tgui/interfaces/NtosCrewManifest.jsx index d8830fe79af..b0f17d449eb 100644 --- a/tgui/packages/tgui/interfaces/NtosCrewManifest.jsx +++ b/tgui/packages/tgui/interfaces/NtosCrewManifest.jsx @@ -26,7 +26,7 @@ export const NtosCrewManifest = (props) => { /> } > - {map((entries, department) => ( + {map(manifest, (entries, department) => (
    {entries.map((entry) => ( @@ -45,7 +45,7 @@ export const NtosCrewManifest = (props) => { ))}
    - ))(manifest)} + ))}
    diff --git a/tgui/packages/tgui/interfaces/NtosEmojipedia.tsx b/tgui/packages/tgui/interfaces/NtosEmojipedia.tsx index 3852e90ac26..d9e6c7233ee 100644 --- a/tgui/packages/tgui/interfaces/NtosEmojipedia.tsx +++ b/tgui/packages/tgui/interfaces/NtosEmojipedia.tsx @@ -3,7 +3,7 @@ import { createSearch } from 'common/string'; import { useState } from 'react'; import { useBackend } from '../backend'; -import { Button, Image, Input, Section } from '../components'; +import { Button, Image, Input, Section, Tooltip } from '../components'; import { NtosWindow } from '../layouts'; type Data = { @@ -44,15 +44,15 @@ export const NtosEmojipedia = (props) => { } > {filteredEmojis.map((emoji) => ( - { - copyText(emoji.name); - }} - /> + + { + copyText(emoji.name); + }} + /> + ))} diff --git a/tgui/packages/tgui/interfaces/NtosMessenger/index.tsx b/tgui/packages/tgui/interfaces/NtosMessenger/index.tsx index 852ca62cc55..896ca90d602 100644 --- a/tgui/packages/tgui/interfaces/NtosMessenger/index.tsx +++ b/tgui/packages/tgui/interfaces/NtosMessenger/index.tsx @@ -100,7 +100,8 @@ const ContactsScreen = (props: any) => { const [searchUser, setSearchUser] = useState(''); - const sortByUnreads = sortBy((chat) => chat.unread_messages); + const sortByUnreads = (array: NtChat[]) => + sortBy(array, (chat) => chat.unread_messages); const searchChatByName = createSearch( searchUser, diff --git a/tgui/packages/tgui/interfaces/NtosNetDownloader.tsx b/tgui/packages/tgui/interfaces/NtosNetDownloader.tsx index 0bfdafc7b62..489c443f0c1 100644 --- a/tgui/packages/tgui/interfaces/NtosNetDownloader.tsx +++ b/tgui/packages/tgui/interfaces/NtosNetDownloader.tsx @@ -1,5 +1,4 @@ import { filter, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { scale, toFixed } from 'common/math'; import { BooleanLike } from 'common/react'; import { createSearch } from 'common/string'; @@ -70,20 +69,22 @@ export const NtosNetDownloader = (props) => { searchItem, (program) => program.filedesc, ); - const items = flow([ + let items = searchItem.length > 0 ? // If we have a query, search everything for it. - filter(search) + filter(programs, search) : // Otherwise, show respective programs for the category. - filter((program: ProgramData) => program.category === selectedCategory), - // This sorts all programs in the lists by name and compatibility - sortBy( - (program: ProgramData) => !program.compatible, - (program: ProgramData) => program.filedesc, - ), + filter(programs, (program) => program.category === selectedCategory); + // This sorts all programs in the lists by name and compatibility + items = sortBy( + items, + (program: ProgramData) => !program.compatible, + (program: ProgramData) => program.filedesc, + ); + if (!emagged) { // This filters the list to only contain verified programs - !emagged && filter((program: ProgramData) => program.verifiedsource === 1), - ])(programs); + items = filter(items, (program) => program.verifiedsource === 1); + } const disk_free_space = downloading ? disk_size - Number(toFixed(disk_used + downloadcompletion)) : disk_size - disk_used; diff --git a/tgui/packages/tgui/interfaces/NuclearBomb.jsx b/tgui/packages/tgui/interfaces/NuclearBomb.tsx similarity index 64% rename from tgui/packages/tgui/interfaces/NuclearBomb.jsx rename to tgui/packages/tgui/interfaces/NuclearBomb.tsx index 81b2e622e9d..5cda6d97cbb 100644 --- a/tgui/packages/tgui/interfaces/NuclearBomb.jsx +++ b/tgui/packages/tgui/interfaces/NuclearBomb.tsx @@ -1,32 +1,40 @@ -import { classes } from 'common/react'; +import { BooleanLike, classes } from 'common/react'; import { useBackend } from '../backend'; -import { Box, Button, Flex, Grid, Icon } from '../components'; +import { Box, Button, Icon, Stack } from '../components'; import { Window } from '../layouts'; +type Data = { + disk_present: BooleanLike; + status1: string; + status2: string; + anchored: BooleanLike; +}; + +const KEYPAD = [ + ['1', '4', '7', 'C'], + ['2', '5', '8', '0'], + ['3', '6', '9', 'E'], +] as const; + // This ui is so many manual overrides and !important tags // and hand made width sets that changing pretty much anything // is going to require a lot of tweaking it get it looking correct again // I'm sorry, but it looks bangin -export const NukeKeypad = (props) => { +export function NukeKeypad(props) { const { act } = useBackend(); - const keypadKeys = [ - ['1', '4', '7', 'C'], - ['2', '5', '8', '0'], - ['3', '6', '9', 'E'], - ]; + return ( - - {keypadKeys.map((keyColumn) => ( - + + {KEYPAD.map((keyColumn) => ( + {keyColumn.map((key) => ( ))} - + ))} - + ); -}; +} + +export function NuclearBomb(props) { + const { act, data } = useBackend(); + const { status1, status2 } = data; -export const NuclearBomb = (props) => { - const { act, data } = useBackend(); - const { anchored, disk_present, status1, status2 } = data; return ( - - + + {status1} - - + + {status2} - - + + - - + + ); -}; +} diff --git a/tgui/packages/tgui/interfaces/Orbit/helpers.ts b/tgui/packages/tgui/interfaces/Orbit/helpers.ts index 8ad071c699b..c0668dd02d8 100644 --- a/tgui/packages/tgui/interfaces/Orbit/helpers.ts +++ b/tgui/packages/tgui/interfaces/Orbit/helpers.ts @@ -1,5 +1,4 @@ import { filter, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { HEALTH, THREAT } from './constants'; import type { AntagGroup, Antagonist, Observable } from './types'; @@ -18,7 +17,7 @@ export const getAntagCategories = (antagonists: Antagonist[]) => { categories[antag_group].push(player); }); - return sortBy(([key]) => key)(Object.entries(categories)); + return sortBy(Object.entries(categories), ([key]) => key); }; /** Returns a disguised name in case the person is wearing someone else's ID */ @@ -43,15 +42,19 @@ export const getMostRelevant = ( searchQuery: string, observables: Observable[][], ): Observable => { - return flow([ - // Filters out anything that doesn't match search - filter((observable) => - isJobOrNameMatch(observable, searchQuery), - ), + const queriedObservables = // Sorts descending by orbiters - sortBy((observable) => -(observable.orbiters || 0)), - // Makes a single Observables list for an easy search - ])(observables.flat())[0]; + sortBy( + // Filters out anything that doesn't match search + filter( + observables + // Makes a single Observables list for an easy search + .flat(), + (observable) => isJobOrNameMatch(observable, searchQuery), + ), + (observable) => -(observable.orbiters || 0), + ); + return queriedObservables[0]; }; /** Returns the display color for certain health percentages */ diff --git a/tgui/packages/tgui/interfaces/Orbit/index.tsx b/tgui/packages/tgui/interfaces/Orbit/index.tsx index 0d992d981a8..0103fe8750f 100644 --- a/tgui/packages/tgui/interfaces/Orbit/index.tsx +++ b/tgui/packages/tgui/interfaces/Orbit/index.tsx @@ -1,5 +1,4 @@ import { filter, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { capitalizeFirst, multiline } from 'common/string'; import { useBackend, useLocalState } from 'tgui/backend'; import { @@ -204,16 +203,13 @@ const ObservableSection = (props: { const [searchQuery] = useLocalState('searchQuery', ''); - const filteredSection: Observable[] = flow([ - filter((observable) => - isJobOrNameMatch(observable, searchQuery), - ), - sortBy((observable) => + const filteredSection = sortBy( + filter(section, (observable) => isJobOrNameMatch(observable, searchQuery)), + (observable) => getDisplayName(observable.full_name, observable.name) .replace(/^"/, '') .toLowerCase(), - ), - ])(section); + ); if (!filteredSection.length) { return null; diff --git a/tgui/packages/tgui/interfaces/PersonalCrafting.tsx b/tgui/packages/tgui/interfaces/PersonalCrafting.tsx index 2a848073769..96ec4b818b3 100644 --- a/tgui/packages/tgui/interfaces/PersonalCrafting.tsx +++ b/tgui/packages/tgui/interfaces/PersonalCrafting.tsx @@ -1,5 +1,4 @@ import { filter, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { BooleanLike, classes } from 'common/react'; import { createSearch } from 'common/string'; import { useState } from 'react'; @@ -186,44 +185,44 @@ export const PersonalCrafting = (props) => { const [activeType, setFoodType] = useState( Object.keys(craftability).length ? 'Can Make' : data.foodtypes[0], ); - const material_occurences = flow([ - sortBy((material) => -material.occurences), - ])(data.material_occurences); + const material_occurences = sortBy( + data.material_occurences, + (material) => -material.occurences, + ); const [activeMaterial, setMaterial] = useState( material_occurences[0].atom_id, ); const [tabMode, setTabMode] = useState(0); const searchName = createSearch(searchText, (item: Recipe) => item.name); - let recipes = flow([ - filter( - (recipe) => - // If craftable only is selected, then filter by craftability - (!display_craftable_only || Boolean(craftability[recipe.ref])) && - // Ignore categories and types when searching - (searchText.length > 0 || - // Is foodtype mode and the active type matches - (tabMode === TABS.foodtype && - mode === MODE.cooking && - ((activeType === 'Can Make' && Boolean(craftability[recipe.ref])) || - recipe.foodtypes?.includes(activeType))) || - // Is material mode and the active material or catalysts match - (tabMode === TABS.material && - Object.keys(recipe.reqs).includes(activeMaterial)) || - // Is category mode and the active categroy matches - (tabMode === TABS.category && - ((activeCategory === 'Can Make' && - Boolean(craftability[recipe.ref])) || - recipe.category === activeCategory))), - ), - sortBy((recipe) => [ - activeCategory === 'Can Make' - ? 99 - Object.keys(recipe.reqs).length - : Number(craftability[recipe.ref]), - recipe.name.toLowerCase(), - ]), - ])(data.recipes); + let recipes = filter( + data.recipes, + (recipe) => + // If craftable only is selected, then filter by craftability + (!display_craftable_only || Boolean(craftability[recipe.ref])) && + // Ignore categories and types when searching + (searchText.length > 0 || + // Is foodtype mode and the active type matches + (tabMode === TABS.foodtype && + mode === MODE.cooking && + ((activeType === 'Can Make' && Boolean(craftability[recipe.ref])) || + recipe.foodtypes?.includes(activeType))) || + // Is material mode and the active material or catalysts match + (tabMode === TABS.material && + Object.keys(recipe.reqs).includes(activeMaterial)) || + // Is category mode and the active categroy matches + (tabMode === TABS.category && + ((activeCategory === 'Can Make' && + Boolean(craftability[recipe.ref])) || + recipe.category === activeCategory))), + ); + recipes = sortBy(recipes, (recipe) => [ + activeCategory === 'Can Make' + ? 99 - Object.keys(recipe.reqs).length + : Number(craftability[recipe.ref]), + recipe.name.toLowerCase(), + ]); if (searchText.length > 0) { - recipes = recipes.filter(searchName); + recipes = filter(recipes, searchName); } const canMake = ['Can Make']; const categories = canMake diff --git a/tgui/packages/tgui/interfaces/Photocopier.jsx b/tgui/packages/tgui/interfaces/Photocopier.jsx index 29353918e19..e1b8b74bb0a 100644 --- a/tgui/packages/tgui/interfaces/Photocopier.jsx +++ b/tgui/packages/tgui/interfaces/Photocopier.jsx @@ -178,7 +178,7 @@ const Blanks = (props) => { const { act, data } = useBackend(); const { blanks, categories, category } = data; - const sortedBlanks = sortBy((blank) => blank.name)(blanks || []); + const sortedBlanks = sortBy(blanks || [], (blank) => blank.name); const selectedCategory = category ?? categories[0]; const visibleBlanks = sortedBlanks.filter( diff --git a/tgui/packages/tgui/interfaces/PlaneMasterDebug.tsx b/tgui/packages/tgui/interfaces/PlaneMasterDebug.tsx index b045304c4ca..1a623bb2079 100644 --- a/tgui/packages/tgui/interfaces/PlaneMasterDebug.tsx +++ b/tgui/packages/tgui/interfaces/PlaneMasterDebug.tsx @@ -158,7 +158,7 @@ const sortConnectionRefs = function ( direction: ConnectionDirection, connectSources: AssocConnected, ) { - refs = sortBy((connection: ConnectionRef) => connection.sort_by)(refs); + refs = sortBy(refs, (connection: ConnectionRef) => connection.sort_by); refs.map((connection, index) => { let connectSource = connectSources[connection.ref]; if (direction === ConnectionDirection.Outgoing) { @@ -264,14 +264,15 @@ const positionPlanes = (connectSources: AssocConnected) => { // and get rid of the now unneeded parent refs const stack = depth_stack.map((layer) => flow([ - sortBy((plane: string) => plane_info[plane].plane), - sortBy((plane: string) => { - const read_from = plane_info[layer[plane]]; - if (!read_from) { - return 0; - } - return read_from.plane; - }), + (planes) => sortBy(planes, (plane: string) => plane_info[plane].plane), + (planes) => + sortBy(planes, (plane: string) => { + const read_from = plane_info[layer[plane]]; + if (!read_from) { + return 0; + } + return read_from.plane; + }), ])(Object.keys(layer)), ); @@ -932,7 +933,7 @@ const AddModal = (props) => { ); const plane_list = Object.keys(plane_info).map((plane) => plane_info[plane]); - const planes = sortBy((plane: Plane) => -plane.plane)(plane_list); + const planes = sortBy(plane_list, (plane: Plane) => -plane.plane); const plane_options = planes.map((plane) => plane.name); diff --git a/tgui/packages/tgui/interfaces/PortableChemMixer.tsx b/tgui/packages/tgui/interfaces/PortableChemMixer.tsx index fc0b4cbb95e..9ffbe06b943 100644 --- a/tgui/packages/tgui/interfaces/PortableChemMixer.tsx +++ b/tgui/packages/tgui/interfaces/PortableChemMixer.tsx @@ -26,8 +26,9 @@ export const PortableChemMixer = (props) => { const { act, data } = useBackend(); const { beaker } = data; const beakerTransferAmounts = beaker ? beaker.transferAmounts : []; - const chemicals = sortBy((chem: DispensableReagent) => chem.id)( + const chemicals = sortBy( data.chemicals, + (chem: DispensableReagent) => chem.id, ); return ( diff --git a/tgui/packages/tgui/interfaces/PowerMonitor.jsx b/tgui/packages/tgui/interfaces/PowerMonitor.jsx index 6e0e0dca173..039e700f68c 100644 --- a/tgui/packages/tgui/interfaces/PowerMonitor.jsx +++ b/tgui/packages/tgui/interfaces/PowerMonitor.jsx @@ -48,18 +48,22 @@ export const PowerMonitorContent = (props) => { const maxValue = Math.max(PEAK_DRAW, ...history.supply, ...history.demand); // Process area data const areas = flow([ - map((area, i) => ({ - ...area, - // Generate a unique id - id: area.name + i, - })), - sortByField === 'name' && sortBy((area) => area.name), - sortByField === 'charge' && sortBy((area) => -area.charge), + (areas) => + map(areas, (area, i) => ({ + ...area, + // Generate a unique id + id: area.name + i, + })), + sortByField === 'name' && ((areas) => sortBy(areas, (area) => area.name)), + sortByField === 'charge' && + ((areas) => sortBy(areas, (area) => -area.charge)), sortByField === 'draw' && - sortBy( - (area) => -powerRank(area.load), - (area) => -parseFloat(area.load), - ), + ((areas) => + sortBy( + areas, + (area) => -powerRank(area.load), + (area) => -parseFloat(area.load), + )), ])(data.areas); return ( <> diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/AntagsPage.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/AntagsPage.tsx index 2ff85058da6..c00889536e0 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/AntagsPage.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/AntagsPage.tsx @@ -25,9 +25,10 @@ const antagsByCategory = new Map(); // This will break at priorities higher than 10, but that almost definitely // will not happen. -const binaryInsertAntag = binaryInsertWith((antag: Antagonist) => { - return `${antag.priority}_${antag.name}`; -}); +const binaryInsertAntag = (collection: Antagonist[], value: Antagonist) => + binaryInsertWith(collection, value, (antag) => { + return `${antag.priority}_${antag.name}`; + }); for (const antagKey of requireAntag.keys()) { const antag = requireAntag<{ diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/GamePreferencesPage.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/GamePreferencesPage.tsx index 05845ffe548..ad81b2c27fd 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/GamePreferencesPage.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/GamePreferencesPage.tsx @@ -13,11 +13,13 @@ type PreferenceChild = { children: ReactNode; }; -const binaryInsertPreference = binaryInsertWith( - (child) => child.name, -); +const binaryInsertPreference = ( + collection: PreferenceChild[], + value: PreferenceChild, +) => binaryInsertWith(collection, value, (child) => child.name); -const sortByName = sortBy<[string, PreferenceChild[]]>(([name]) => name); +const sortByName = (array: [string, PreferenceChild[]][]) => + sortBy(array, ([name]) => name); export const GamePreferencesPage = (props) => { const { act, data } = useBackend(); diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/JobsPage.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/JobsPage.tsx index bf40f73049a..10c962a8302 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/JobsPage.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/JobsPage.tsx @@ -14,10 +14,11 @@ import { import { ServerPreferencesFetcher } from './ServerPreferencesFetcher'; const sortJobs = (entries: [string, Job][], head?: string) => - sortBy<[string, Job]>( + sortBy( + entries, ([key, _]) => (key === head ? -1 : 1), ([key, _]) => key, - )(entries); + ); const PRIORITY_BUTTON_SIZE = '18px'; diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/KeybindingsPage.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/KeybindingsPage.tsx index c3b123105ab..32d39c287df 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/KeybindingsPage.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/KeybindingsPage.tsx @@ -67,15 +67,14 @@ const KEY_CODE_TO_BYOND: Record = { */ const DOM_KEY_LOCATION_NUMPAD = 3; -const sortKeybindings = sortBy(([_, keybinding]: [string, Keybinding]) => { - return keybinding.name; -}); +const sortKeybindings = (array: [string, Keybinding][]) => + sortBy(array, ([_, keybinding]) => { + return keybinding.name; + }); -const sortKeybindingsByCategory = sortBy( - ([category, _]: [string, Record]) => { - return category; - }, -); +const sortKeybindingsByCategory = ( + array: [string, Record][], +) => sortBy(array, ([category, _]) => category); const formatKeyboardEvent = (event: KeyboardEvent): string => { let text = ''; @@ -177,12 +176,6 @@ const KeybindingName = (props: { keybinding: Keybinding }) => { ); }; -KeybindingName.defaultHooks = { - onComponentShouldUpdate: (lastProps, nextProps) => { - return lastProps.keybinding !== nextProps.keybinding; - }, -}; - const ResetToDefaultButton = (props: { keybindingId: string }) => { const { act } = useBackend(); diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/MainPage.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/MainPage.tsx index 30766576256..846c05199d2 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/MainPage.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/MainPage.tsx @@ -1,11 +1,9 @@ -import { filterMap, sortBy } from 'common/collections'; +import { filter, map, sortBy } from 'common/collections'; import { exhaustiveCheck } from 'common/exhaustive'; import { classes } from 'common/react'; +import { createSearch } from 'common/string'; import { useState } from 'react'; -import { filter } from '../../../common/collections'; -import { flow } from '../../../common/fp'; -import { createSearch } from '../../../common/string'; import { sendAct, useBackend } from '../../backend'; import { Autofocus, @@ -229,8 +227,14 @@ const ChoicedSelection = (props: { }; const searchInCatalog = (searchText = '', catalog: Record) => { - const maybeSearch = createSearch(searchText, ([name, _icon]) => name); - return flow([searchText && filter(maybeSearch)])(Object.entries(catalog)); + let items = Object.entries(catalog); + if (searchText) { + items = filter( + items, + createSearch(searchText, ([name, _icon]) => name), + ); + } + return items; }; const GenderButton = (props: { @@ -395,10 +399,11 @@ const createSetRandomization = }); }; -const sortPreferences = sortBy<[string, unknown]>(([featureId, _]) => { - const feature = features[featureId]; - return feature?.name; -}); +const sortPreferences = (array: [string, unknown][]) => + sortBy(array, ([featureId, _]) => { + const feature = features[featureId]; + return feature?.name; + }); export const PreferenceList = (props: { act: typeof sendAct; @@ -478,22 +483,20 @@ export const getRandomization = ( const { data } = useBackend(); + if (!randomBodyEnabled) { + return {}; + } + return Object.fromEntries( - filterMap(Object.keys(preferences), (preferenceKey) => { - if (serverData.random.randomizable.indexOf(preferenceKey) === -1) { - return undefined; - } - - if (!randomBodyEnabled) { - return undefined; - } - - return [ - preferenceKey, - data.character_preferences.randomization[preferenceKey] || - RandomSetting.Disabled, - ]; - }), + map( + filter(Object.keys(preferences), (key) => + serverData.random.randomizable.includes(key), + ), + (key) => [ + key, + data.character_preferences.randomization[key] || RandomSetting.Disabled, + ], + ), ); }; diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/QuirksPage.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/QuirksPage.tsx index 15533a1cb35..382dabf4121 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/QuirksPage.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/QuirksPage.tsx @@ -1,4 +1,4 @@ -import { filterMap } from 'common/collections'; +import { filter } from 'common/collections'; import { useState } from 'react'; import { useBackend } from '../../backend'; @@ -23,13 +23,9 @@ function getCorrespondingPreferences( relevant_preferences: Record, ) { return Object.fromEntries( - filterMap(Object.keys(relevant_preferences), (key) => { - if (!customization_options.includes(key)) { - return undefined; - } - - return [key, relevant_preferences[key]]; - }), + filter(Object.entries(relevant_preferences), ([key, value]) => + customization_options.includes(key), + ), ); } diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/names.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/names.tsx index eadb6e94d42..039fb8027ad 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/names.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/names.tsx @@ -21,9 +21,11 @@ type NameWithKey = { name: Name; }; -const binaryInsertName = binaryInsertWith(({ key }) => key); +const binaryInsertName = (collection: NameWithKey[], value: NameWithKey) => + binaryInsertWith(collection, value, ({ key }) => key); -const sortNameWithKeyEntries = sortBy<[string, NameWithKey[]]>(([key]) => key); +const sortNameWithKeyEntries = (array: [string, NameWithKey[]][]) => + sortBy(array, ([key]) => key); export const MultiNameInput = (props: { handleClose: () => void; diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx index b911a196b3c..6da6aec820d 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx @@ -1,4 +1,4 @@ -import { sortBy, sortStrings } from 'common/collections'; +import { sort, sortBy } from 'common/collections'; import { BooleanLike, classes } from 'common/react'; import { ComponentType, @@ -22,7 +22,8 @@ import { import { createSetPreference, PreferencesMenuData } from '../../data'; import { ServerPreferencesFetcher } from '../../ServerPreferencesFetcher'; -export const sortChoices = sortBy<[string, ReactNode]>(([name]) => name); +export const sortChoices = (array: [string, ReactNode][]) => + sortBy(array, ([name]) => name); export type Feature< TReceiving, @@ -210,7 +211,7 @@ export const FeatureDropdownInput = ( return ( ; }; -const sortHexValues = sortBy<[string, HexValue]>( - ([_, hexValue]) => -hexValue.lightness, -); +const sortHexValues = (array: [string, HexValue][]) => + sortBy(array, ([_, hexValue]) => -hexValue.lightness); export const skin_tone: Feature = { name: 'Skin tone', diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ghost.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ghost.tsx index cfa323dce2c..ab973e3659e 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ghost.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/ghost.tsx @@ -22,10 +22,13 @@ export const ghost_accs: FeatureChoiced = { component: FeatureDropdownInput, }; -const insertGhostForm = binaryInsertWith<{ +type GhostForm = { displayText: ReactNode; value: string; -}>(({ value }) => value); +}; + +const insertGhostForm = (collection: GhostForm[], value: GhostForm) => + binaryInsertWith(collection, value, ({ value }) => value); const GhostFormInput = ( props: FeatureValueProps, diff --git a/tgui/packages/tgui/interfaces/Radio.jsx b/tgui/packages/tgui/interfaces/Radio.jsx index d25409e033a..d852149571a 100644 --- a/tgui/packages/tgui/interfaces/Radio.jsx +++ b/tgui/packages/tgui/interfaces/Radio.jsx @@ -23,10 +23,10 @@ export const Radio = (props) => { const tunedChannel = RADIO_CHANNELS.find( (channel) => channel.freq === frequency, ); - const channels = map((value, key) => ({ + const channels = map(data.channels, (value, key) => ({ name: key, status: !!value, - }))(data.channels); + })); // Calculate window height let height = 106; if (subspace) { diff --git a/tgui/packages/tgui/interfaces/RequestsConsole/MessageWriteTab.tsx b/tgui/packages/tgui/interfaces/RequestsConsole/MessageWriteTab.tsx index 5195c451838..117df20b8c0 100644 --- a/tgui/packages/tgui/interfaces/RequestsConsole/MessageWriteTab.tsx +++ b/tgui/packages/tgui/interfaces/RequestsConsole/MessageWriteTab.tsx @@ -1,4 +1,4 @@ -import { sortStrings } from 'common/collections'; +import { sort } from 'common/collections'; import { useState } from 'react'; import { useBackend, useLocalState } from '../../backend'; @@ -22,9 +22,9 @@ export const MessageWriteTab = (props) => { information_consoles = [], } = data; - const sorted_assistance = sortStrings(assistance_consoles); - const sorted_supply = sortStrings(supply_consoles); - const sorted_information = sortStrings(information_consoles); + const sorted_assistance = sort(assistance_consoles); + const sorted_supply = sort(supply_consoles); + const sorted_information = sort(information_consoles); const resetMessage = () => { setMessageText(''); diff --git a/tgui/packages/tgui/interfaces/RestockTracker.jsx b/tgui/packages/tgui/interfaces/RestockTracker.jsx index 236f486069c..7df606adffc 100644 --- a/tgui/packages/tgui/interfaces/RestockTracker.jsx +++ b/tgui/packages/tgui/interfaces/RestockTracker.jsx @@ -17,8 +17,9 @@ export const Restock = (props) => { export const RestockTracker = (props) => { const { data } = useBackend(); - const vending_list = sortBy((vend) => vend.percentage)( + const vending_list = sortBy( data.vending_list ?? [], + (vend) => vend.percentage, ); return (
    diff --git a/tgui/packages/tgui/interfaces/Roulette.jsx b/tgui/packages/tgui/interfaces/Roulette.jsx deleted file mode 100644 index e07cf4e0ef4..00000000000 --- a/tgui/packages/tgui/interfaces/Roulette.jsx +++ /dev/null @@ -1,313 +0,0 @@ -import { classes } from 'common/react'; -import { useState } from 'react'; - -import { useBackend } from '../backend'; -import { Box, Button, Grid, NumberInput, Table } from '../components'; -import { Window } from '../layouts'; - -const getNumberColor = (number) => { - const inRedOddRange = - (number >= 1 && number <= 10) || (number >= 19 && number <= 28); - - if (number % 2 === 1) { - return inRedOddRange ? 'red' : 'black'; - } - return inRedOddRange ? 'black' : 'red'; -}; - -export const RouletteNumberCell = (props) => { - const { - buttonClass = null, - cellClass = null, - color, - colspan = '1', - rowspan = '1', - text, - value, - } = props; - const { act } = useBackend(); - - return ( - - - - ); -}; - -export const RouletteBoard = () => { - const firstRow = [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36]; - const secondRow = [2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35]; - const thirdRow = [1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34]; - const fourthRow = { - 's1-12': '1st 12', - 's13-24': '2nd 12', - 's25-36': '3rd 12', - }; - const fifthRow = [ - { color: 'transparent', text: '1-18', value: 's1-18' }, - { color: 'transparent', text: 'Even', value: 'even' }, - { color: 'black', text: 'Black', value: 'black' }, - { color: 'red', text: 'Red', value: 'red' }, - { color: 'transparent', text: 'Odd', value: 'odd' }, - { color: 'transparent', text: '19-36', value: 's19-36' }, - ]; - - return ( - - - - - {firstRow.map((number) => ( - - ))} - - - - {secondRow.map((number) => ( - - ))} - - - - {thirdRow.map((number) => ( - - ))} - - - - - {Object.entries(fourthRow).map(([value, text]) => ( - - ))} - - - - {fifthRow.map((cell) => ( - - ))} - -
    -
    - ); -}; - -export const RouletteBetTable = (props) => { - const { act, data } = useBackend(); - - const [customBet, setCustomBet] = useState(500); - - let { BetType } = data; - - if (BetType.startsWith('s')) { - BetType = BetType.substring(1, BetType.length); - } - - return ( - - - - Last Spin: - - - Current Bet: - - - - - {data.LastSpin} - - - - {data.BetAmount} cr on {BetType} - - -
    - ); -}; - -export const Roulette = (props) => { - return ( - - - - - - - ); -}; diff --git a/tgui/packages/tgui/interfaces/Roulette/BetTable.tsx b/tgui/packages/tgui/interfaces/Roulette/BetTable.tsx new file mode 100644 index 00000000000..8abf081b288 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Roulette/BetTable.tsx @@ -0,0 +1,171 @@ +import { BooleanLike, classes } from 'common/react'; +import { useState } from 'react'; + +import { useBackend } from '../../backend'; +import { Box, Button, NumberInput, Stack, Table } from '../../components'; +import { getNumberColor } from './helpers'; + +type Data = { + IsAnchored: BooleanLike; + BetAmount: number; + BetType: string; + HouseBalance: number; + LastSpin: number; + Spinning: BooleanLike; + AccountBalance: number; + CanUnbolt: BooleanLike; +}; + +export function RouletteBetTable(props) { + const { act, data } = useBackend(); + const { LastSpin, HouseBalance, BetAmount, IsAnchored } = data; + + const [customBet, setCustomBet] = useState(500); + + let BetType = data.BetType; + + if (BetType.startsWith('s')) { + BetType = BetType.substring(1, BetType.length); + } + + return ( + + + + Last Spin: + + + Current Bet: + + + + + {LastSpin} + + + + {BetAmount} cr on {BetType} + + + + + + + + + + + + setCustomBet(value)} + /> + + + + + + + + + Swipe an ID card with a connected account to spin! + + + + + + + House Balance: + + {HouseBalance ? HouseBalance + ' cr' : 'None'} + + + + + +
    + ); +} diff --git a/tgui/packages/tgui/interfaces/Roulette/Board.tsx b/tgui/packages/tgui/interfaces/Roulette/Board.tsx new file mode 100644 index 00000000000..0f0fbcdc681 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Roulette/Board.tsx @@ -0,0 +1,107 @@ +import { Box, Table } from '../../components'; +import { getNumberColor } from './helpers'; +import { RouletteNumberCell } from './NumberCell'; + +const firstRow = [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36] as const; +const secondRow = [2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35] as const; +const thirdRow = [1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34] as const; +const fourthRow = { + 's1-12': '1st 12', + 's13-24': '2nd 12', + 's25-36': '3rd 12', +} as const; +const fifthRow = [ + { color: 'transparent', text: '1-18', value: 's1-18' }, + { color: 'transparent', text: 'Even', value: 'even' }, + { color: 'black', text: 'Black', value: 'black' }, + { color: 'red', text: 'Red', value: 'red' }, + { color: 'transparent', text: 'Odd', value: 'odd' }, + { color: 'transparent', text: '19-36', value: 's19-36' }, +] as const; + +export function RouletteBoard(props) { + return ( + + + + + {firstRow.map((number) => ( + + ))} + + + + {secondRow.map((number) => ( + + ))} + + + + {thirdRow.map((number) => ( + + ))} + + + + + {Object.entries(fourthRow).map(([value, text]) => ( + + ))} + + + + {fifthRow.map((cell) => ( + + ))} + +
    +
    + ); +} diff --git a/tgui/packages/tgui/interfaces/Roulette/NumberCell.tsx b/tgui/packages/tgui/interfaces/Roulette/NumberCell.tsx new file mode 100644 index 00000000000..1b8143905c3 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Roulette/NumberCell.tsx @@ -0,0 +1,48 @@ +import { classes } from 'common/react'; + +import { useBackend } from '../../backend'; +import { Button, Table } from '../../components'; + +type Props = { + color: string; + text: string; + value: string; +} & Partial<{ + buttonClass: string; + cellClass: string; + colspan: number; + rowspan: number; +}>; + +export function RouletteNumberCell(props: Props) { + const { + buttonClass, + cellClass, + color, + colspan = 1, + rowspan = 1, + text, + value, + } = props; + const { act } = useBackend(); + + return ( + + + + ); +} diff --git a/tgui/packages/tgui/interfaces/Roulette/helpers.tsx b/tgui/packages/tgui/interfaces/Roulette/helpers.tsx new file mode 100644 index 00000000000..b5c4f9b9b33 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Roulette/helpers.tsx @@ -0,0 +1,9 @@ +export function getNumberColor(number: number): 'red' | 'black' { + const inRedOddRange = + (number >= 1 && number <= 10) || (number >= 19 && number <= 28); + + if (number % 2 === 1) { + return inRedOddRange ? 'red' : 'black'; + } + return inRedOddRange ? 'black' : 'red'; +} diff --git a/tgui/packages/tgui/interfaces/Roulette/index.tsx b/tgui/packages/tgui/interfaces/Roulette/index.tsx new file mode 100644 index 00000000000..8c27a052a02 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Roulette/index.tsx @@ -0,0 +1,14 @@ +import { Window } from '../../layouts'; +import { RouletteBetTable } from './BetTable'; +import { RouletteBoard } from './Board'; + +export function Roulette(props) { + return ( + + + + + + + ); +} diff --git a/tgui/packages/tgui/interfaces/SecurityRecords/RecordTabs.tsx b/tgui/packages/tgui/interfaces/SecurityRecords/RecordTabs.tsx index 8132027e3e6..8241148257a 100644 --- a/tgui/packages/tgui/interfaces/SecurityRecords/RecordTabs.tsx +++ b/tgui/packages/tgui/interfaces/SecurityRecords/RecordTabs.tsx @@ -1,5 +1,4 @@ import { filter, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { useState } from 'react'; import { useBackend, useLocalState } from 'tgui/backend'; import { @@ -29,10 +28,10 @@ export const SecurityRecordTabs = (props) => { const [search, setSearch] = useState(''); - const sorted: SecurityRecord[] = flow([ - filter((record: SecurityRecord) => isRecordMatch(record, search)), - sortBy((record: SecurityRecord) => record.name), - ])(records); + const sorted = sortBy( + filter(records, (record) => isRecordMatch(record, search)), + (record) => record.name, + ); return ( diff --git a/tgui/packages/tgui/interfaces/SeedExtractor.tsx b/tgui/packages/tgui/interfaces/SeedExtractor.tsx index 3c05b3d0498..87955da243f 100644 --- a/tgui/packages/tgui/interfaces/SeedExtractor.tsx +++ b/tgui/packages/tgui/interfaces/SeedExtractor.tsx @@ -1,5 +1,4 @@ import { sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { classes } from 'common/react'; import { createSearch } from 'common/string'; import { useState } from 'react'; @@ -67,9 +66,10 @@ export const SeedExtractor = (props) => { const search = createSearch(searchText, (item: SeedData) => item.name); const seeds_filtered = searchText.length > 0 ? data.seeds.filter(search) : data.seeds; - const seeds = flow([ - sortBy((item: SeedData) => item[sortField as keyof SeedData]), - ])(seeds_filtered || []); + const seeds = sortBy( + seeds_filtered || [], + (item: SeedData) => item[sortField as keyof SeedData], + ); sortField !== 'name' && seeds.reverse(); return ( diff --git a/tgui/packages/tgui/interfaces/SelectEquipment.jsx b/tgui/packages/tgui/interfaces/SelectEquipment.jsx index d43d28961e2..d8df6c71e7c 100644 --- a/tgui/packages/tgui/interfaces/SelectEquipment.jsx +++ b/tgui/packages/tgui/interfaces/SelectEquipment.jsx @@ -1,5 +1,4 @@ import { filter, map, sortBy, uniq } from 'common/collections'; -import { flow } from 'common/fp'; import { createSearch } from 'common/string'; import { useState } from 'react'; @@ -30,10 +29,10 @@ export const SelectEquipment = (props) => { const isFavorited = (entry) => favorites?.includes(entry.path); - const outfits = map((entry) => ({ + const outfits = map([...data.outfits, ...data.custom_outfits], (entry) => ({ ...entry, favorite: isFavorited(entry), - }))([...data.outfits, ...data.custom_outfits]); + })); // even if no custom outfits were sent, we still want to make sure there's // at least a 'Custom' tab so the button to create a new one pops up @@ -49,15 +48,15 @@ export const SelectEquipment = (props) => { (entry) => entry.name + entry.path, ); - const visibleOutfits = flow([ - filter((entry) => entry.category === tab), - filter(searchFilter), - sortBy( - (entry) => !entry.favorite, - (entry) => !entry.priority, - (entry) => entry.name, + const visibleOutfits = sortBy( + filter( + filter(outfits, (entry) => entry.category === tab), + searchFilter, ), - ])(outfits); + (entry) => !entry.favorite, + (entry) => !entry.priority, + (entry) => entry.name, + ); const getOutfitEntry = (current_outfit) => outfits.find((outfit) => getOutfitKey(outfit) === current_outfit); diff --git a/tgui/packages/tgui/interfaces/ShuttleManipulator.jsx b/tgui/packages/tgui/interfaces/ShuttleManipulator.jsx index e64f47086cd..8cff913e8e9 100644 --- a/tgui/packages/tgui/interfaces/ShuttleManipulator.jsx +++ b/tgui/packages/tgui/interfaces/ShuttleManipulator.jsx @@ -104,7 +104,7 @@ export const ShuttleManipulatorTemplates = (props) => { - {map((template, templateId) => ( + {map(templateObject, (template, templateId) => ( { > {template.port_id} - ))(templateObject)} + ))} diff --git a/tgui/packages/tgui/interfaces/StackCrafting.tsx b/tgui/packages/tgui/interfaces/StackCrafting.tsx index 255d8f501f1..7395306c11a 100644 --- a/tgui/packages/tgui/interfaces/StackCrafting.tsx +++ b/tgui/packages/tgui/interfaces/StackCrafting.tsx @@ -1,5 +1,3 @@ -import { filter, map, reduce, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { clamp } from 'common/math'; import { createSearch } from 'common/string'; import { useState } from 'react'; @@ -49,8 +47,7 @@ type RecipeBoxProps = { }; // RecipeList converted via Object.entries() for filterRecipeList -type RecipeListEntry = [string, RecipeList | Recipe]; -type RecipeListFilterableEntry = [string, RecipeList | Recipe | undefined]; +type RecipeListFilterableEntry = [string, RecipeList | Recipe]; /** * Type guard for recipe vs recipe list @@ -70,30 +67,29 @@ function isRecipeList(value: Recipe | RecipeList): value is RecipeList { const filterRecipeList = ( list: RecipeList, keyFilter: (key: string) => boolean, -) => { - const filteredList: RecipeList = flow([ - map((entry: RecipeListEntry): RecipeListFilterableEntry => { - const [key, recipe] = entry; +): RecipeList | undefined => { + const filteredList = Object.fromEntries( + Object.entries(list) + .flatMap((entry): RecipeListFilterableEntry[] => { + const [key, recipe] = entry; - if (isRecipeList(recipe)) { // If category name matches, return the whole thing. if (keyFilter(key)) { - return entry; + return [entry]; } - // otherwise, filter sub-entries. - return [key, filterRecipeList(recipe, keyFilter)]; - } + if (isRecipeList(recipe)) { + // otherwise, filter sub-entries. + const subEntries = filterRecipeList(recipe, keyFilter); + if (subEntries !== undefined) { + return [[key, subEntries]]; + } + } - return keyFilter(key) ? entry : [key, undefined]; - }), - filter((entry: RecipeListFilterableEntry) => entry[1] !== undefined), - sortBy((entry: RecipeListEntry) => entry[0].toLowerCase()), - reduce((obj: RecipeList, entry: RecipeListEntry) => { - obj[entry[0]] = entry[1]; - return obj; - }, {}), - ])(Object.entries(list)); + return []; + }) + .sort(([a], [b]) => (a < b ? -1 : a !== b ? 1 : 0)), + ); return Object.keys(filteredList).length ? filteredList : undefined; }; diff --git a/tgui/packages/tgui/interfaces/StationAlertConsole.jsx b/tgui/packages/tgui/interfaces/StationAlertConsole.jsx index f80a5826b06..c4ff6812955 100644 --- a/tgui/packages/tgui/interfaces/StationAlertConsole.jsx +++ b/tgui/packages/tgui/interfaces/StationAlertConsole.jsx @@ -1,5 +1,4 @@ import { sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { useBackend } from '../backend'; import { Button, Section, Stack } from '../components'; @@ -30,8 +29,9 @@ export const StationAlertConsoleContent = (props) => { Camera: 5, }; - const sortedAlarms = flow([sortBy((alarm) => sortingKey[alarm.name])])( + const sortedAlarms = sortBy( data.alarms || [], + (alarm) => sortingKey[alarm.name], ); return ( diff --git a/tgui/packages/tgui/interfaces/StationTraitsPanel.tsx b/tgui/packages/tgui/interfaces/StationTraitsPanel.tsx index f3176415a4f..e6e7b02ce67 100644 --- a/tgui/packages/tgui/interfaces/StationTraitsPanel.tsx +++ b/tgui/packages/tgui/interfaces/StationTraitsPanel.tsx @@ -1,4 +1,4 @@ -import { filterMap } from 'common/collections'; +import { filter, map } from 'common/collections'; import { exhaustiveCheck } from 'common/exhaustive'; import { BooleanLike } from 'common/react'; import { useState } from 'react'; @@ -110,15 +110,9 @@ const FutureStationTraitsPage = (props) => { icon="times" onClick={() => { act('setup_future_traits', { - station_traits: filterMap( - future_station_traits, - (otherTrait) => { - if (otherTrait.path === trait.path) { - return undefined; - } else { - return otherTrait.path; - } - }, + station_traits: filter( + map(future_station_traits, (t) => t.path), + (p) => p !== trait.path, ), }); }} diff --git a/tgui/packages/tgui/interfaces/Supermatter.tsx b/tgui/packages/tgui/interfaces/Supermatter.tsx index 9bb8661ca29..35d176db6cd 100644 --- a/tgui/packages/tgui/interfaces/Supermatter.tsx +++ b/tgui/packages/tgui/interfaces/Supermatter.tsx @@ -1,5 +1,4 @@ import { filter, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { toFixed } from 'common/math'; import { BooleanLike } from 'common/react'; import { ReactNode, useState } from 'react'; @@ -123,10 +122,14 @@ export const SupermatterContent = (props: SupermatterProps) => { gas_metadata, } = props; const [allGasActive, setAllGasActive] = useState(false); - const gas_composition: [gas_path: string, amount: number][] = flow([ - !allGasActive && filter(([gas_path, amount]) => amount !== 0), - sortBy(([gas_path, amount]) => -amount), - ])(Object.entries(props.gas_composition)); + let gas_composition = Object.entries(props.gas_composition); + if (!allGasActive) { + gas_composition = filter( + gas_composition, + ([gas_path, amount]) => amount !== 0, + ); + } + gas_composition = sortBy(gas_composition, ([gas_path, amount]) => -amount); return ( diff --git a/tgui/packages/tgui/interfaces/SurgeryInitiator.tsx b/tgui/packages/tgui/interfaces/SurgeryInitiator.tsx index 2e9403794bf..c051315fe3b 100644 --- a/tgui/packages/tgui/interfaces/SurgeryInitiator.tsx +++ b/tgui/packages/tgui/interfaces/SurgeryInitiator.tsx @@ -20,7 +20,8 @@ type SurgeryInitiatorData = { target_name: string; }; -const sortSurgeries = sortBy((surgery: Surgery) => surgery.name); +const sortSurgeries = (array: Surgery[]) => + sortBy(array, (surgery) => surgery.name); type SurgeryInitiatorInnerState = { selectedSurgeryIndex: number; diff --git a/tgui/packages/tgui/interfaces/SyndContractor.jsx b/tgui/packages/tgui/interfaces/SyndContractor.jsx index 472a1834df6..5daa40b1195 100644 --- a/tgui/packages/tgui/interfaces/SyndContractor.jsx +++ b/tgui/packages/tgui/interfaces/SyndContractor.jsx @@ -11,6 +11,7 @@ import { Modal, NoticeBox, Section, + Stack, Table, Tabs, } from '../components'; @@ -181,8 +182,8 @@ export const StatusPane = (props) => { } > - - + + { {String(data.earned_tc)} - - + + {String(data.contracts_completed)} ACTIVE - - + +
    ); }; diff --git a/tgui/packages/tgui/interfaces/SyndicateContractor.tsx b/tgui/packages/tgui/interfaces/SyndicateContractor.tsx index 81e01d682d7..66c07263981 100644 --- a/tgui/packages/tgui/interfaces/SyndicateContractor.tsx +++ b/tgui/packages/tgui/interfaces/SyndicateContractor.tsx @@ -5,32 +5,21 @@ import { Box, Button, Flex, - Grid, Icon, LabeledList, Modal, NoticeBox, Section, + Stack, } from '../components'; import { FakeTerminal } from '../components/FakeTerminal'; import { NtosWindow } from '../layouts'; -const CONTRACT_STATUS_INACTIVE = 1; -const CONTRACT_STATUS_ACTIVE = 2; -const CONTRACT_STATUS_BOUNTY_CONSOLE_ACTIVE = 3; -const CONTRACT_STATUS_EXTRACTING = 4; -const CONTRACT_STATUS_COMPLETE = 5; -const CONTRACT_STATUS_ABORTED = 6; - -export const SyndicateContractor = (props) => { - return ( - - - - - - ); -}; +enum CONTRACT { + Inactive = 1, + Active = 2, + Complete = 5, +} type Data = { contracts_completed: number; @@ -59,7 +48,47 @@ type ContractData = { target: string; }; -export const SyndicateContractorContent = (props) => { +const infoEntries = [ + 'SyndTract v2.0', + '', + "We've identified potentional high-value targets that are", + 'currently assigned to your mission area. They are believed', + 'to hold valuable information which could be of immediate', + 'importance to our organisation.', + '', + 'Listed below are all of the contracts available to you. You', + 'are to bring the specified target to the designated', + 'drop-off, and contact us via this uplink. We will send', + 'a specialised extraction unit to put the body into.', + '', + 'We want targets alive - but we will sometimes pay slight', + "amounts if they're not, you just won't receive the shown", + 'bonus. You can redeem your payment through this uplink in', + 'the form of raw telecrystals, which can be put into your', + 'regular Syndicate uplink to purchase whatever you may need.', + 'We provide you with these crystals the moment you send the', + 'target up to us, which can be collected at anytime through', + 'this system.', + '', + 'Targets extracted will be ransomed back to the station once', + 'their use to us is fulfilled, with us providing you a small', + 'percentage cut. You may want to be mindful of them', + 'identifying you when they come back. We provide you with', + 'a standard contractor loadout, which will help cover your', + 'identity.', +] as const; + +export function SyndicateContractor(props) { + return ( + + + + + + ); +} + +function SyndicateContractorContent(props) { const { data, act } = useBackend(); const { error, logged_in, first_load, info_screen } = data; @@ -84,37 +113,7 @@ export const SyndicateContractorContent = (props) => { 'Searching for available contracts...', 'CONTRACTS FOUND', 'WELCOME, AGENT', - ]; - - const infoEntries = [ - 'SyndTract v2.0', - '', - "We've identified potentional high-value targets that are", - 'currently assigned to your mission area. They are believed', - 'to hold valuable information which could be of immediate', - 'importance to our organisation.', - '', - 'Listed below are all of the contracts available to you. You', - 'are to bring the specified target to the designated', - 'drop-off, and contact us via this uplink. We will send', - 'a specialised extraction unit to put the body into.', - '', - 'We want targets alive - but we will sometimes pay slight', - "amounts if they're not, you just won't receive the shown", - 'bonus. You can redeem your payment through this uplink in', - 'the form of raw telecrystals, which can be put into your', - 'regular Syndicate uplink to purchase whatever you may need.', - 'We provide you with these crystals the moment you send the', - 'target up to us, which can be collected at anytime through', - 'this system.', - '', - 'Targets extracted will be ransomed back to the station once', - 'their use to us is fulfilled, with us providing you a small', - 'percentage cut. You may want to be mindful of them', - 'identifying you when they come back. We provide you with', - 'a standard contractor loadout, which will help cover your', - 'identity.', - ]; + ] as const; const errorPane = !!error && ( @@ -126,7 +125,7 @@ export const SyndicateContractorContent = (props) => { {error} - @@ -136,11 +135,9 @@ export const SyndicateContractorContent = (props) => { return (
    - {!!error && {error}}
    @@ -167,11 +164,12 @@ export const SyndicateContractorContent = (props) => {
    ); } @@ -183,38 +181,38 @@ export const SyndicateContractorContent = (props) => { ); -}; +} -export const StatusPane = (props) => { +function StatusPane(props) { const { act, data } = useBackend(); const { redeemable_tc, earned_tc, contracts_completed } = data; return (
    - Contractor Status - } + title="Contractor Status" > - - + + act('PRG_redeem_TC')} - /> + > + Claim + } > {String(redeemable_tc)} @@ -223,24 +221,28 @@ export const StatusPane = (props) => { {String(earned_tc)} - - + + {String(contracts_completed)} ACTIVE - - + +
    ); -}; +} -const ContractsTab = (props) => { +function ContractsTab(props) { const { act, data } = useBackend(); - const { contracts, ongoing_contract, extraction_enroute, dropoff_direction } = - data; + const { + contracts = [], + ongoing_contract, + extraction_enroute, + dropoff_direction, + } = data; return ( <> @@ -248,18 +250,19 @@ const ContractsTab = (props) => { title="Available Contracts" buttons={ } > {contracts.map((contract) => { - if (ongoing_contract && contract.status !== CONTRACT_STATUS_ACTIVE) { + if (ongoing_contract && contract.status !== CONTRACT.Active) { return; } - const active = contract.status > CONTRACT_STATUS_INACTIVE; - if (contract.status >= CONTRACT_STATUS_COMPLETE) { + const active = contract.status > CONTRACT.Inactive; + if (contract.status >= CONTRACT.Complete) { return; } return ( @@ -276,27 +279,28 @@ const ContractsTab = (props) => { {`${contract.payout} (+${contract.payout_bonus}) TC`}
    } > - - {contract.message} - + + {contract.message} + Dropoff Location: {contract.dropoff} - - + + ); })} @@ -310,4 +314,4 @@ const ContractsTab = (props) => { ); -}; +} diff --git a/tgui/packages/tgui/interfaces/Techweb.jsx b/tgui/packages/tgui/interfaces/Techweb.jsx index 96b52983ade..c041d646d7d 100644 --- a/tgui/packages/tgui/interfaces/Techweb.jsx +++ b/tgui/packages/tgui/interfaces/Techweb.jsx @@ -41,9 +41,9 @@ const selectRemappedStaticData = (data) => { ...node, id: remapId(id), costs, - prereq_ids: map(remapId)(node.prereq_ids || []), - design_ids: map(remapId)(node.design_ids || []), - unlock_ids: map(remapId)(node.unlock_ids || []), + prereq_ids: map(node.prereq_ids || [], remapId), + design_ids: map(node.design_ids || [], remapId), + unlock_ids: map(node.unlock_ids || [], remapId), required_experiments: node.required_experiments || [], discount_experiments: node.discount_experiments || [], }; @@ -251,10 +251,11 @@ const TechwebOverview = (props) => { ); }); } else { - displayedNodes = sortBy((x) => node_cache[x.id].name)( + displayedNodes = sortBy( tabIndex < 2 ? nodes.filter((x) => x.tier === tabIndex) : nodes.filter((x) => x.tier >= tabIndex), + (x) => node_cache[x.id].name, ); } diff --git a/tgui/packages/tgui/interfaces/TrackedPlaytime.jsx b/tgui/packages/tgui/interfaces/TrackedPlaytime.jsx index 3f1a3dcb543..f59b01b8b5d 100644 --- a/tgui/packages/tgui/interfaces/TrackedPlaytime.jsx +++ b/tgui/packages/tgui/interfaces/TrackedPlaytime.jsx @@ -7,7 +7,7 @@ import { Window } from '../layouts'; const JOB_REPORT_MENU_FAIL_REASON_TRACKING_DISABLED = 1; const JOB_REPORT_MENU_FAIL_REASON_NO_RECORDS = 2; -const sortByPlaytime = sortBy(([_, playtime]) => -playtime); +const sortByPlaytime = (array) => sortBy(array, ([_, playtime]) => -playtime); const PlaytimeSection = (props) => { const { playtimes } = props; diff --git a/tgui/packages/tgui/interfaces/WarrantConsole.tsx b/tgui/packages/tgui/interfaces/WarrantConsole.tsx index 14415b3ee79..a87de8e017c 100644 --- a/tgui/packages/tgui/interfaces/WarrantConsole.tsx +++ b/tgui/packages/tgui/interfaces/WarrantConsole.tsx @@ -63,7 +63,7 @@ export const WarrantConsole = (props) => { const RecordList = (props) => { const { act, data } = useBackend(); const { records = [] } = data; - const sorted = sortBy((record: WarrantRecord) => record.crew_name)(records); + const sorted = sortBy(records, (record) => record.crew_name); const [selectedRecord, setSelectedRecord] = useLocalState< WarrantRecord | undefined diff --git a/tgui/packages/tgui/interfaces/common/AccessConfig.jsx b/tgui/packages/tgui/interfaces/common/AccessConfig.jsx deleted file mode 100644 index e91abecbde7..00000000000 --- a/tgui/packages/tgui/interfaces/common/AccessConfig.jsx +++ /dev/null @@ -1,136 +0,0 @@ -import { sortBy } from 'common/collections'; -import { useState } from 'react'; - -import { Button, Flex, Grid, Section, Tabs } from '../../components'; - -export const AccessConfig = (props) => { - const { - accesses = [], - selectedList = [], - accessMod, - grantAll, - denyAll, - grantDep, - denyDep, - } = props; - const [selectedAccessName, setSelectedAccessName] = useState( - accesses[0]?.name, - ); - const selectedAccess = accesses.find( - (access) => access.name === selectedAccessName, - ); - const selectedAccessEntries = sortBy((entry) => entry.desc)( - selectedAccess?.accesses || [], - ); - - const checkAccessIcon = (accesses) => { - let oneAccess = false; - let oneInaccess = false; - for (let element of accesses) { - if (selectedList.includes(element.ref)) { - oneAccess = true; - } else { - oneInaccess = true; - } - } - if (!oneAccess && oneInaccess) { - return 0; - } else if (oneAccess && oneInaccess) { - return 1; - } else { - return 2; - } - }; - - return ( -
    -
    - ); -}; - -const diffMap = { - 0: { - icon: 'times-circle', - color: 'bad', - }, - 1: { - icon: 'stop-circle', - color: null, - }, - 2: { - icon: 'check-circle', - color: 'good', - }, -}; diff --git a/tgui/packages/tgui/interfaces/common/AccessConfig.tsx b/tgui/packages/tgui/interfaces/common/AccessConfig.tsx new file mode 100644 index 00000000000..766a6724d77 --- /dev/null +++ b/tgui/packages/tgui/interfaces/common/AccessConfig.tsx @@ -0,0 +1,204 @@ +import { sortBy } from 'common/collections'; +import { useState } from 'react'; + +import { Button, Section, Stack, Tabs } from '../../components'; + +type BaseProps = { + accessMod: (ref: string) => void; + denyDep: (ref: string) => void; + grantDep: (ref: string) => void; +}; + +type ConfigProps = { + accesses: Region[]; + denyAll: () => void; + grantAll: () => void; + selectedList: string[]; +} & BaseProps; + +type AccessButtonProps = { + selectedAccess: Region; + selectedAccessEntries: Area[]; + selectedList: string[]; +} & BaseProps; + +export type Region = { + accesses: Area[]; + name: string; +}; + +export type Area = { + desc: string; + ref: string; +}; + +enum ACCESS { + Denied = 0, + Partial = 1, + Granted = 2, +} + +const DIFFMAP = [ + { + icon: 'times-circle', + color: 'bad', + }, + { + icon: 'stop-circle', + color: null, + }, + { + icon: 'check-circle', + color: 'good', + }, +] as const; + +export function AccessConfig(props: ConfigProps) { + const { + accesses = [], + selectedList = [], + accessMod, + grantAll, + denyAll, + grantDep, + denyDep, + } = props; + + const [selectedAccessName, setSelectedAccessName] = useState( + accesses[0]?.name, + ); + + const selectedAccess = + accesses.find((access) => access.name === selectedAccessName) || + accesses[0]; + + const selectedAccessEntries = sortBy( + selectedAccess?.accesses || [], + (entry: Area) => entry.desc, + ); + + function checkAccessIcon(accesses: Area[]) { + let oneAccess = false; + let oneInaccess = false; + for (let element of accesses) { + if (selectedList.includes(element.ref)) { + oneAccess = true; + } else { + oneInaccess = true; + } + } + if (!oneAccess && oneInaccess) { + return ACCESS.Denied; + } else if (oneAccess && oneInaccess) { + return ACCESS.Partial; + } else { + return ACCESS.Granted; + } + } + + return ( +
    + + + + } + > + + + + {accesses.map((access) => { + const entries = access.accesses || []; + const icon = DIFFMAP[checkAccessIcon(entries)].icon; + const color = DIFFMAP[checkAccessIcon(entries)].color; + return ( + setSelectedAccessName(access.name)} + > + {access.name} + + ); + })} + + + + + + + +
    + ); +} + +function AccessButtons(props: AccessButtonProps) { + const { + selectedAccessEntries, + selectedList, + accessMod, + grantDep, + denyDep, + selectedAccess, + } = props; + + return ( + + + + + + + + + + + + + +
    + {selectedAccessEntries.map((entry) => ( + accessMod(entry.ref)} + > + {entry.desc} + + ))} +
    +
    +
    + ); +} diff --git a/tgui/packages/tgui/interfaces/common/AccessList.jsx b/tgui/packages/tgui/interfaces/common/AccessList.jsx index a4096b6ce30..9ac1fe913b3 100644 --- a/tgui/packages/tgui/interfaces/common/AccessList.jsx +++ b/tgui/packages/tgui/interfaces/common/AccessList.jsx @@ -248,8 +248,9 @@ const RegionAccessList = (props) => { const selectedAccess = accesses.find( (access) => access.name === selectedAccessName, ); - const selectedAccessEntries = sortBy((entry) => entry.desc)( + const selectedAccessEntries = sortBy( selectedAccess?.accesses || [], + (entry) => entry.desc, ); const allWildcards = Object.keys(wildcardSlots); diff --git a/tgui/packages/tgui/interfaces/common/BeakerDisplay.tsx b/tgui/packages/tgui/interfaces/common/BeakerDisplay.tsx index 6c2d3649325..3483c3ceede 100644 --- a/tgui/packages/tgui/interfaces/common/BeakerDisplay.tsx +++ b/tgui/packages/tgui/interfaces/common/BeakerDisplay.tsx @@ -8,7 +8,7 @@ import { Section, } from '../../components'; -type BeakerReagent = { +export type BeakerReagent = { name: string; volume: number; }; diff --git a/tgui/packages/tgui/layouts/Layout.tsx b/tgui/packages/tgui/layouts/Layout.tsx index 74aad987d21..173ed1cbb43 100644 --- a/tgui/packages/tgui/layouts/Layout.tsx +++ b/tgui/packages/tgui/layouts/Layout.tsx @@ -5,6 +5,7 @@ */ import { classes } from 'common/react'; +import { useEffect, useRef } from 'react'; import { BoxProps, @@ -40,6 +41,20 @@ type ContentProps = Partial<{ function LayoutContent(props: ContentProps) { const { className, scrollable, children, ...rest } = props; + const node = useRef(null); + + useEffect(() => { + const self = node.current; + + if (self && scrollable) { + addScrollableNode(self); + } + return () => { + if (self && scrollable) { + removeScrollableNode(self); + } + }; + }, []); return (
    {children} @@ -56,9 +72,4 @@ function LayoutContent(props: ContentProps) { ); } -LayoutContent.defaultHooks = { - onComponentDidMount: (node) => addScrollableNode(node), - onComponentWillUnmount: (node) => removeScrollableNode(node), -}; - Layout.Content = LayoutContent; diff --git a/tgui/packages/tgui/layouts/Pane.tsx b/tgui/packages/tgui/layouts/Pane.tsx index a2858fae7fc..f34205545fb 100644 --- a/tgui/packages/tgui/layouts/Pane.tsx +++ b/tgui/packages/tgui/layouts/Pane.tsx @@ -9,6 +9,7 @@ import { classes } from 'common/react'; import { useBackend } from '../backend'; import { Box } from '../components'; import { BoxProps } from '../components/Box'; +import { useDebug } from '../debug'; import { Layout } from './Layout'; type Props = Partial<{ @@ -18,11 +19,8 @@ type Props = Partial<{ export function Pane(props: Props) { const { theme, children, className, ...rest } = props; - const { suspended, debug } = useBackend(); - let debugLayout = false; - if (debug) { - debugLayout = debug.debugLayout; - } + const { suspended } = useBackend(); + const { debugLayout = false } = useDebug(); return ( diff --git a/tgui/packages/tgui/layouts/Window.tsx b/tgui/packages/tgui/layouts/Window.tsx index 2b6fbf87356..aa91370bfc3 100644 --- a/tgui/packages/tgui/layouts/Window.tsx +++ b/tgui/packages/tgui/layouts/Window.tsx @@ -13,6 +13,7 @@ import { globalStore } from '../backend'; import { Icon } from '../components'; import { BoxProps } from '../components/Box'; import { UI_DISABLED, UI_INTERACTIVE, UI_UPDATE } from '../constants'; +import { useDebug } from '../debug'; import { toggleKitchenSink } from '../debug/actions'; import { dragStartHandler, @@ -48,10 +49,8 @@ export const Window = (props: Props) => { height, } = props; - const { config, suspended, debug } = useBackend(); - if (suspended) { - return null; - } + const { config, suspended } = useBackend(); + const { debugLayout = false } = useDebug(); useEffect(() => { const updateGeometry = () => { @@ -80,11 +79,6 @@ export const Window = (props: Props) => { }; }, [width, height]); - let debugLayout = false; - if (debug) { - debugLayout = debug.debugLayout; - } - const dispatch = globalStore.dispatch; const fancy = config.window?.fancy; @@ -95,11 +89,11 @@ export const Window = (props: Props) => { ? config.status < UI_DISABLED : config.status < UI_INTERACTIVE); - return ( + return suspended ? null : ( { // Get the component for the current route export const getRoutedComponent = () => { - const { suspended, config, debug } = useBackend(); + const { suspended, config } = useBackend(); + const { kitchenSink = false } = useDebug(); + if (suspended) { return SuspendedWindow; } @@ -61,7 +64,7 @@ export const getRoutedComponent = () => { } if (process.env.NODE_ENV !== 'production') { // Show a kitchen sink - if (debug?.kitchenSink) { + if (kitchenSink) { return require('./debug').KitchenSink; } } diff --git a/tgui/packages/tgui/styles/components/SearchItem.scss b/tgui/packages/tgui/styles/components/SearchItem.scss new file mode 100644 index 00000000000..76946ec9c5a --- /dev/null +++ b/tgui/packages/tgui/styles/components/SearchItem.scss @@ -0,0 +1,22 @@ +@use '../colors.scss'; + +.SearchItem { + align-items: center; + background: black; + border: thin solid #212121; + display: flex; + height: 3rem; + justify-content: center; + position: relative; + width: 3rem; + margin-bottom: 0; +} + +.SearchItem--amount { + bottom: -1rem; + color: colors.$teal; + font-family: 'Roboto', sans-serif; + font-size: 1.5rem; + position: absolute; + right: -4px; +} diff --git a/tgui/packages/tgui/styles/main.scss b/tgui/packages/tgui/styles/main.scss index 25443ae606c..87715e2ae30 100644 --- a/tgui/packages/tgui/styles/main.scss +++ b/tgui/packages/tgui/styles/main.scss @@ -38,6 +38,7 @@ @include meta.load-css('./components/NumberInput.scss'); @include meta.load-css('./components/ProgressBar.scss'); @include meta.load-css('./components/RoundGauge.scss'); +@include meta.load-css('./components/SearchItem.scss'); @include meta.load-css('./components/Section.scss'); @include meta.load-css('./components/Slider.scss'); @include meta.load-css('./components/Stack.scss'); diff --git a/tools/UpdatePaths/Scripts/74147_tech_disk_repath.txt b/tools/UpdatePaths/Scripts/74147_tech_disk_repath.txt index 6b5a0e4c5e6..2111d891fc3 100644 --- a/tools/UpdatePaths/Scripts/74147_tech_disk_repath.txt +++ b/tools/UpdatePaths/Scripts/74147_tech_disk_repath.txt @@ -1,7 +1,7 @@ # removes advanced design, and moves bepis tech disks to its new type /obj/item/disk/design_disk/adv : /obj/item/disk/design_disk{@OLD} -/obj/item/disk/design_disk/adv/@SUBTPYES : /obj/item/disk/design_disk/@SUBTYPES{@OLD} +/obj/item/disk/design_disk/adv/@SUBTYPES : /obj/item/disk/design_disk/@SUBTYPES{@OLD} /obj/item/disk/tech_disk/major : /obj/item/disk/design_disk/bepis/remove_tech /obj/item/disk/tech_disk/spaceloot : /obj/item/disk/design_disk/bepis diff --git a/tools/UpdatePaths/Scripts/82565_blueprints_repath.txt b/tools/UpdatePaths/Scripts/82565_blueprints_repath.txt new file mode 100644 index 00000000000..08ff26217cf --- /dev/null +++ b/tools/UpdatePaths/Scripts/82565_blueprints_repath.txt @@ -0,0 +1 @@ +/obj/item/areaeditor/@SUBTYPES{@OLD} : /obj/item/blueprints/@SUBTYPES{@OLD} diff --git a/tools/ci/check_grep.sh b/tools/ci/check_grep.sh index 8763cca749e..5a3606d71ed 100644 --- a/tools/ci/check_grep.sh +++ b/tools/ci/check_grep.sh @@ -152,6 +152,16 @@ if $grep -i '(add_traits|remove_traits)\(.+,\s*src\)' $code_files; then st=1 fi; +part "ensure proper lowertext usage" +# lowertext() is a BYOND-level proc, so it can be used in any sort of code... including the TGS DMAPI which we don't manage in this repository. +# basically, we filter out any results with "tgs" in it to account for this edgecase without having to enforce this rule in that separate codebase. +# grepping the grep results is a bit of a sad solution to this but it's pretty much the only option in our existing linter framework +if $grep -i 'lowertext\(.+\)' $code_files | $grep -v 'UNLINT\(.+\)' | $grep -v '\/modules\/tgs\/'; then + echo + echo -e "${RED}ERROR: Found a lowertext() proc call. Please use the LOWER_TEXT() macro instead. If you know what you are doing, wrap your text (ensure it is a string) in UNLINT().${NC}" + st=1 +fi; + part "balloon_alert sanity" if $grep 'balloon_alert\(".*"\)' $code_files; then echo diff --git a/tools/test_merge_bot/main.js b/tools/test_merge_bot/main.js index 0ad51304ecf..ae7d4c7a98d 100644 --- a/tools/test_merge_bot/main.js +++ b/tools/test_merge_bot/main.js @@ -87,19 +87,41 @@ export async function processTestMerges({ github, context }) { } if (existingComment === undefined) { - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - body: newBody, - }); + try { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: newBody, + }); + } catch (error) { + if(error.status){ + console.error(`Failed to create comment for #{prNumber}`) + console.error(error) + continue; + } + else{ + throw error + } + } } else { - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: existingComment.databaseId, - body: newBody, - }); + try { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existingComment.databaseId, + body: newBody, + }); + } catch (error) { + if(error.status){ + console.error(`Failed to update comment for #{prNumber}`) + console.error(error) + continue; + } + else{ + throw error + } + } } } }