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/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/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_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 d926cc6d5df..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) 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/mobs.dm b/code/__DEFINES/mobs.dm index e46600abe2a..f47ad817e92 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -855,6 +855,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 ea5b929651d..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_DEBRIS_AFTER_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/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 ccd7e4e06bb..d7ec3e4669c 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -191,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/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index f5ad67a8c94..6a83f33083a 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -767,6 +767,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" 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/~skyrat_defines/combat.dm b/code/__DEFINES/~skyrat_defines/combat.dm index 5137aa81376..05474bb21d8 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/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index f210774ac81..e0f07ab2835 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -152,15 +152,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( @@ -282,20 +281,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, + "INFINITE_RESKIN" = INFINITE_RESKIN, + "CONDUCTS_ELECTRICITY" = CONDUCTS_ELECTRICITY, "NO_DEBRIS_AFTER_DECONSTRUCTION" = NO_DEBRIS_AFTER_DECONSTRUCTION, - "UNIQUE_RENAME" = UNIQUE_RENAME, )) DEFINE_BITFIELD(pass_flags, list( diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 83e199cb908..f67ed4f6d07 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -362,6 +362,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, @@ -418,7 +419,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, @@ -440,6 +440,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, diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm index d4c203342e4..5fe6883e82b 100644 --- a/code/_globalvars/traits/admin_tooling.dm +++ b/code/_globalvars/traits/admin_tooling.dm @@ -160,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, @@ -192,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, @@ -206,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/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/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 1576c342273..7b1394ada16 100644 --- a/code/controllers/subsystem/statpanel.dm +++ b/code/controllers/subsystem/statpanel.dm @@ -110,12 +110,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 @@ -188,71 +182,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( @@ -294,16 +223,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 @@ -323,105 +242,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/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/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/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 a17e642e039..ffcf81feace 100644 --- a/code/datums/components/material/material_container.dm +++ b/code/datums/components/material/material_container.dm @@ -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/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/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/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/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/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/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 f6712455ac3..ea25c5f957f 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/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/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/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/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/storage/storage.dm b/code/datums/storage/storage.dm index 87398f52555..b1bacfbceab 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -916,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) 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_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/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index fb8a4ce139f..533c3aa1a42 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -338,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. @@ -423,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 @@ -590,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 @@ -668,10 +668,8 @@ //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, datum/tgui/ui, datum/ui_state/state) add_fingerprint(usr) @@ -769,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)) 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/camera/camera.dm b/code/game/machinery/camera/camera.dm index b096633a9c1..ca6562635ee 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -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/civilian_bounties.dm b/code/game/machinery/civilian_bounties.dm index d2a584a1675..1cb7ee1477e 100644 --- a/code/game/machinery/civilian_bounties.dm +++ b/code/game/machinery/civilian_bounties.dm @@ -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 index 1bfd43cdb69..69994634fc3 100644 --- a/code/game/machinery/computer/arcade/_arcade.dm +++ b/code/game/machinery/computer/arcade/_arcade.dm @@ -12,11 +12,7 @@ ///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, is_right_clicking) - . = ..() - if(. & ITEM_INTERACT_ANY_BLOCKER) - return . - +/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)) @@ -44,6 +40,8 @@ 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) @@ -100,5 +98,3 @@ 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/battle.dm b/code/game/machinery/computer/arcade/battle.dm index 5586f3f8b22..63d2808c773 100644 --- a/code/game/machinery/computer/arcade/battle.dm +++ b/code/game/machinery/computer/arcade/battle.dm @@ -113,6 +113,8 @@ 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 @@ -216,7 +218,7 @@ 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 - to_chat(user, span_notice("[src] dispenses 2 tickets!")) + visible_message(span_notice("[src] dispenses 2 tickets!")) new /obj/item/stack/arcadeticket((get_turf(src)), 2) player_gold += enemy_gold_reward if(user) @@ -282,12 +284,14 @@ process_enemy_turn(user) ///Called when you successfully counterattack the enemy. -/obj/machinery/computer/arcade/battle/proc/successful_counterattack() +/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. @@ -346,7 +350,7 @@ 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() + return successful_counterattack(user) return user_take_damage(user, damage_dealt) /obj/machinery/computer/arcade/battle/ui_data(mob/user) diff --git a/code/game/machinery/computer/arcade/battle_gear.dm b/code/game/machinery/computer/arcade/battle_gear.dm index 7a91df0e058..32d1d73dd4f 100644 --- a/code/game/machinery/computer/arcade/battle_gear.dm +++ b/code/game/machinery/computer/arcade/battle_gear.dm @@ -2,7 +2,7 @@ ///The name of the gear, used in shops. var/name = "Gear" ///The slot this gear fits into - var/slot = WEAPON_SLOT + 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 @@ -95,7 +95,7 @@ bonus_modifier = 4 /datum/battle_arcade_gear/tier_7/armor - name = "Celestial Armor" + name = "Ethereal Armor" slot = ARMOR_SLOT bonus_modifier = 4 @@ -103,11 +103,24 @@ 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_8/armor - name = "Ethereal Armor" +/datum/battle_arcade_gear/tier_9/armor + name = "Void Armor" slot = ARMOR_SLOT bonus_modifier = 5 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_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index 488331c41b8..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 @@ -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 ca3329298cb..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) . = ..() 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/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/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/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/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/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/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 51b0a5b6a5d..bb93b7d00f5 100644 --- a/code/game/machinery/slotmachine.dm +++ b/code/game/machinery/slotmachine.dm @@ -94,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 a8d4d62544b..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 @@ -36,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/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/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_bioscrambler.dm b/code/game/objects/effects/anomalies/anomalies_bioscrambler.dm index 214440b92c2..f1034c5541f 100644 --- a/code/game/objects/effects/anomalies/anomalies_bioscrambler.dm +++ b/code/game/objects/effects/anomalies/anomalies_bioscrambler.dm @@ -29,22 +29,29 @@ 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(20)) - var/mob/living/new_target = find_nearest_target() - if (isnull(new_target)) - pursuit_target = null - else if (new_target != current_target) - current_target = new_target - pursuit_target = WEAKREF(new_target) - new_target.ominous_nosebleed() - if (isnull(pursuit_target)) + if (!isnull(pursuit_target) && prob(80)) return - var/turf/step_turf = get_step(src, get_dir(src, current_target)) - if (!HAS_TRAIT(step_turf, TRAIT_CONTAINMENT_FIELD)) - Move(step_turf) + 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() @@ -53,8 +60,8 @@ for(var/mob/living/carbon/target in GLOB.player_list) if (target.z != z) continue - if (target.status_effects & GODMODE) - 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) @@ -64,3 +71,9 @@ 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/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 57600813df1..9bc73ba2592 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 @@ -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) 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/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 ae0dca8d195..4cb077808a8 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -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/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/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 6bda55c8032..b9f2090eeb4 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -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 fcc9257e4b5..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)) diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm index 7f672e7d32a..1a264cf3924 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()) @@ -489,17 +493,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" @@ -596,7 +596,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/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/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/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/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 9cfdce50fe3..847807ee9f4 100644 --- a/code/game/objects/items/robot/items/hypo.dm +++ b/code/game/objects/items/robot/items/hypo.dm @@ -245,13 +245,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 3d1696cc303..885a97a9329 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) diff --git a/code/game/objects/items/spear.dm b/code/game/objects/items/spear.dm index 5590bfd3c2f..401ffd46934 100644 --- a/code/game/objects/items/spear.dm +++ b/code/game/objects/items/spear.dm @@ -160,13 +160,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 75c35eabb18..4e8a01971ba 100644 --- a/code/game/objects/items/stacks/bscrystal.dm +++ b/code/game/objects/items/stacks/bscrystal.dm @@ -67,6 +67,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) @@ -74,7 +75,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 4d02057d30a..280e009210c 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -150,7 +150,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \ resistance_flags = FIRE_PROOF merge_type = /obj/item/stack/sheet/iron grind_results = list(/datum/reagent/iron = 20) - point_value = 6 + gulag_valid = TRUE tableVariant = /obj/structure/table material_type = /datum/material/iron matter_amount = 4 @@ -277,7 +277,7 @@ GLOBAL_LIST_INIT(plasteel_recipes, list ( \ resistance_flags = FIRE_PROOF merge_type = /obj/item/stack/sheet/plasteel grind_results = list(/datum/reagent/iron = 20, /datum/reagent/toxin/plasma = 20) - point_value = 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/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 1354b57f16f..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 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..359f9c17c7b 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 /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/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/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/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 8ac1ee98994..6a5b6357a8f 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1402,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_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/objs.dm b/code/game/objects/objs.dm index e8797836bae..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("", "---") @@ -270,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)) @@ -331,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 92c955977e7..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" 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/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 4a201cba5b8..acbd7bfa395 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -580,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) @@ -592,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/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/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 a1deed332ab..59247b768a0 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 @@ -298,12 +299,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/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 f1c4516316d..29c93fcda25 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -862,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 2acac966f23..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) ..() 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/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/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/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/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/art/paintings.dm b/code/modules/art/paintings.dm index a4758eb9e11..f050528bd3b 100644 --- a/code/modules/art/paintings.dm +++ b/code/modules/art/paintings.dm @@ -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)) 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/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 d8d0ed3b47e..d152cf09e71 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -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/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/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 2220f640541..02f0d203544 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/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm index 3d4e2b02e1f..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 @@ -162,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/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/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/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/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 4a81fa96ffa..b3e18ce5b0c 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -549,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() @@ -589,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 @@ -621,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 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/head/jobs.dm b/code/modules/clothing/head/jobs.dm index 67ecc0d4859..b300ff99179 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/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 6d5e328b0d6..48c85ac57aa 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/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm index 02db0145ae7..e30dfc2f5ac 100644 --- a/code/modules/clothing/shoes/_shoes.dm +++ b/code/modules/clothing/shoes/_shoes.dm @@ -181,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) @@ -196,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) @@ -210,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/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/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 2d6b3a21b65..7194046b196 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) . = ..() @@ -349,17 +353,14 @@ 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/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/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/fishing/aquarium/aquarium.dm b/code/modules/fishing/aquarium/aquarium.dm index fe281d7e511..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) . = ..() 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 8135dd8308f..ef9aac9a410 100644 --- a/code/modules/food_and_drinks/machinery/oven.dm +++ b/code/modules/food_and_drinks/machinery/oven.dm @@ -99,15 +99,24 @@ 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 @@ -243,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/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/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 d32795e90c3..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) . = ..() diff --git a/code/modules/jobs/job_types/prisoner.dm b/code/modules/jobs/job_types/prisoner.dm index 5f5f01ea33f..53d220da80a 100644 --- a/code/modules/jobs/job_types/prisoner.dm +++ b/code/modules/jobs/job_types/prisoner.dm @@ -69,9 +69,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/lootpanel/_lootpanel.dm b/code/modules/lootpanel/_lootpanel.dm new file mode 100644 index 00000000000..339a79d77fa --- /dev/null +++ b/code/modules/lootpanel/_lootpanel.dm @@ -0,0 +1,75 @@ +/** + * ## Loot panel + * A datum that stores info containing the contents of a turf. + * Handles opening the lootpanel UI and searching the turf for items. + */ +/datum/lootpanel + /// The owner of the panel + var/client/owner + /// The list of all search objects indexed. + var/list/datum/search_object/contents = list() + /// The list of search_objects needing processed + var/list/datum/search_object/to_image = list() + /// We've been notified about client version + var/notified = FALSE + /// The turf being searched + var/turf/source_turf + + +/datum/lootpanel/New(client/owner) + . = ..() + + src.owner = owner + + +/datum/lootpanel/Destroy(force) + reset_contents() + owner = null + source_turf = null + + return ..() + + +/datum/lootpanel/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "LootPanel") + ui.set_autoupdate(FALSE) + ui.open() + + +/datum/lootpanel/ui_close(mob/user) + . = ..() + + source_turf = null + reset_contents() + + +/datum/lootpanel/ui_data(mob/user) + var/list/data = list() + + data["contents"] = get_contents() + data["searching"] = length(to_image) + + return data + + +/datum/lootpanel/ui_status(mob/user, datum/ui_state/state) + if(user.incapacitated()) + return UI_DISABLED + + return UI_INTERACTIVE + + +/datum/lootpanel/ui_act(action, list/params) + . = ..() + if(.) + return + + switch(action) + if("grab") + return grab(usr, params) + if("refresh") + return populate_contents() + + return FALSE diff --git a/code/modules/lootpanel/contents.dm b/code/modules/lootpanel/contents.dm new file mode 100644 index 00000000000..4bb255b1561 --- /dev/null +++ b/code/modules/lootpanel/contents.dm @@ -0,0 +1,49 @@ +/// Adds the item to contents and to_image (if needed) +/datum/lootpanel/proc/add_to_index(datum/search_object/index) + RegisterSignal(index, COMSIG_QDELETING, PROC_REF(on_searchable_deleted)) + if(isnull(index.icon)) + to_image += index + + contents += index + + +/// Used to populate contents and start generating if needed +/datum/lootpanel/proc/populate_contents() + if(length(contents)) + reset_contents() + + // Add source turf first + var/datum/search_object/source = new(owner, source_turf) + add_to_index(source) + + for(var/atom/thing as anything in source_turf.contents) + // validate + if(thing.mouse_opacity == MOUSE_OPACITY_TRANSPARENT) + continue + if(thing.IsObscured()) + continue + if(thing.invisibility > 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/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/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 f30fd24ae6c..5795eed1d74 100644 --- a/code/modules/mining/boulder_processing/_boulder_processing.dm +++ b/code/modules/mining/boulder_processing/_boulder_processing.dm @@ -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/equipment/explorer_gear.dm b/code/modules/mining/equipment/explorer_gear.dm index 10ba871176f..4845b0f9c00 100644 --- a/code/modules/mining/equipment/explorer_gear.dm +++ b/code/modules/mining/equipment/explorer_gear.dm @@ -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 diff --git a/code/modules/mining/equipment/marker_beacons.dm b/code/modules/mining/equipment/marker_beacons.dm index 9a7913278e8..c33181dd806 100644 --- a/code/modules/mining/equipment/marker_beacons.dm +++ b/code/modules/mining/equipment/marker_beacons.dm @@ -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" @@ -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 2c8a6af7864..4fdd997fcab 100644 --- a/code/modules/mining/equipment/mining_tools.dm +++ b/code/modules/mining/equipment/mining_tools.dm @@ -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/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/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/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm index 3e262468298..98a771a06a9 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 c86160db025..ccd4b0d617f 100644 --- a/code/modules/mob/living/basic/bots/_bots.dm +++ b/code/modules/mob/living/basic/bots/_bots.dm @@ -41,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. @@ -362,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) 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/brain/posibrain.dm b/code/modules/mob/living/brain/posibrain.dm index a59e5021948..9df1697e400 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 a88002321d8..8a524d5e222 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) 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/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/human_stripping.dm b/code/modules/mob/living/carbon/human/human_stripping.dm index 41a00b59359..b2dce5234b4 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/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/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/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 7dcdfe54496..e37981d038a 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1405,9 +1405,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 @@ -1851,7 +1856,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 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/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/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 6527205c2c7..4018207b6fa 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) @@ -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 @@ -1616,9 +1618,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/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/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 3bf46f16d1b..b55fb6d2ee6 100644 --- a/code/modules/modular_computers/computers/item/laptop.dm +++ b/code/modules/modular_computers/computers/item/laptop.dm @@ -91,14 +91,11 @@ 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) 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/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/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/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm index a0a51da165f..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 @@ -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 132d882dbee..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) . = ..() 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 7ed187929df..f9a5ae47598 100644 --- a/code/modules/plumbing/plumbers/iv_drip.dm +++ b/code/modules/plumbing/plumbers/iv_drip.dm @@ -29,8 +29,6 @@ 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/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/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/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/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index 456577d3981..b206e1977f4 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -496,18 +496,16 @@ 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() 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 7850dd59f46..1d53eff0f9b 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -1204,7 +1204,6 @@ 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) bullet.impacted[WEAKREF(thing)] = TRUE bullet.firer = firer || src 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 fa3448c392f..9f210e12ee4 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -174,9 +174,9 @@ ) return containers -/obj/machinery/chem_master/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) +/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 ..() + return NONE if(is_reagent_container(tool) && tool.is_open_container()) replace_beaker(user, tool) @@ -186,7 +186,7 @@ else return ITEM_INTERACT_BLOCKING - return ..() + return NONE /obj/machinery/chem_master/wrench_act(mob/living/user, obj/item/tool) if(user.combat_mode) @@ -406,7 +406,7 @@ return FALSE //use energy - if(!use_energy(active_power_usage)) + if(!use_energy(active_power_usage, force = FALSE)) return FALSE //do the operation @@ -518,7 +518,9 @@ return //use power - if(!use_energy(active_power_usage)) + if(!use_energy(active_power_usage, force = FALSE)) + is_printing = FALSE + update_appearance(UPDATE_OVERLAYS) return //print the stuff 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 f02d0d47deb..e206ffebbc9 100644 --- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm +++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm @@ -211,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()) @@ -262,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/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 a6e4dd42885..ea0eaf989dd 100644 --- a/code/modules/reagents/reagent_containers/cups/_cup.dm +++ b/code/modules/reagents/reagent_containers/cups/_cup.dm @@ -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/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/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/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/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/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/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/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 172959153aa..9724bd776d8 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -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 3d4d9bc4b45..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)) 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/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 b1d613f4091..abf3575f39e 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -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 6e83c413216..9d1453e2123 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -377,7 +377,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/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/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 88f18d2cb7d..eb648666030 100644 --- a/code/modules/transport/tram/tram_signals.dm +++ b/code/modules/transport/tram/tram_signals.dm @@ -169,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) . = ..() diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index be41b619ed6..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" 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/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 9fea0ebe82f..2dce26624ad 100644 --- a/code/modules/vehicles/mecha/mech_fabricator.dm +++ b/code/modules/vehicles/mecha/mech_fabricator.dm @@ -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/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/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/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 d80f3ae7c16..dceae8cbbce 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/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/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/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/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 1779812105a..cf4a4202fc8 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/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/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/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/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 66e4e209dab..6d692728674 100644 --- a/modular_skyrat/modules/colony_fabricator/code/machines/arc_furnace.dm +++ b/modular_skyrat/modules/colony_fabricator/code/machines/arc_furnace.dm @@ -107,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/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/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 e8688a96b1a..b68119246c1 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 = HIDEFACE | HIDESNOUT 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/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/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 82f55eabd24..ba8ea2defbb 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/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/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_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/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_energy_master.dm b/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm index dfa8c97adea..6dce4269ef8 100644 --- a/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm +++ b/modular_skyrat/modules/microfusion/code/microfusion_energy_master.dm @@ -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/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 fb6f72e832e..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 @@ -310,7 +310,7 @@ return FALSE replace_beaker(user, used_container) - updateUsrDialog() + SStgui.update_uis(src) return TRUE // Beaker change handler @@ -586,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/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_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/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_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/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/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 3a909a7d87a..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) 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/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/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/sound/attributions.txt b/sound/attributions.txt index 39f206e982a..be8df17c535 100644 --- a/sound/attributions.txt +++ b/sound/attributions.txt @@ -143,3 +143,7 @@ where refinery and wooping_teleport are modifications of that same electric dril 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/tgstation.dme b/tgstation.dme index 2d6844b2f66..de3803c651c 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -61,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" @@ -648,6 +649,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" @@ -845,7 +847,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" @@ -1219,6 +1220,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" @@ -1460,6 +1462,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" @@ -1541,6 +1544,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" @@ -1560,6 +1564,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" @@ -1587,6 +1592,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" @@ -1830,6 +1836,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" @@ -2225,6 +2232,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" @@ -2799,6 +2807,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" @@ -3401,6 +3410,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" @@ -4484,6 +4494,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" 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/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/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/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 6dd79e19bdf..b334e460cea 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/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/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 + } + } } } }