diff --git a/_maps/RandomRuins/JungleRuins/jungle_cavecrew.dmm b/_maps/RandomRuins/JungleRuins/jungle_cavecrew.dmm index 781ae59a84f4..dec4c65755f9 100644 --- a/_maps/RandomRuins/JungleRuins/jungle_cavecrew.dmm +++ b/_maps/RandomRuins/JungleRuins/jungle_cavecrew.dmm @@ -1762,7 +1762,7 @@ /turf/open/floor/plasteel/tech, /area/ruin/jungle/cavecrew/security) "vr" = ( -/obj/machinery/computer/cargo/express, +/obj/machinery/computer/cargo, /turf/open/floor/plasteel/patterned, /area/ruin/jungle/cavecrew/cargo) "vH" = ( diff --git a/_maps/RandomRuins/SpaceRuins/singularity_lab.dmm b/_maps/RandomRuins/SpaceRuins/singularity_lab.dmm index 45591d25dde5..99ccda138d00 100644 --- a/_maps/RandomRuins/SpaceRuins/singularity_lab.dmm +++ b/_maps/RandomRuins/SpaceRuins/singularity_lab.dmm @@ -3490,7 +3490,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer2{ dir = 9 }, -/obj/machinery/computer/cargo/express, +/obj/machinery/computer/cargo, /turf/open/floor/carpet/nanoweave/beige, /area/ruin/space/has_grav/singularitylab/cargo) "nT" = ( diff --git a/_maps/configs/independent_sunskipper.json b/_maps/configs/independent_sunskipper.json index 08a4a56f9fde..ee17e126cc34 100644 --- a/_maps/configs/independent_sunskipper.json +++ b/_maps/configs/independent_sunskipper.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/shiptest-ss13/Shiptest/master/_maps/ship_config_schema.json", "map_name": "Sunskipper-class Culinary Vessel", - "prefix": "ISV", + "prefix": "SV", "namelists": ["CRUISE", "NATURAL"], "map_short_name": "Sunskipper-class", "map_path": "_maps/shuttles/independent/independent_sunskipper.dmm", diff --git a/_maps/outpost/hangar/nt_asteroid_20x20.dmm b/_maps/outpost/hangar/nt_asteroid_20x20.dmm index 118f810e93f8..858d984f4603 100644 --- a/_maps/outpost/hangar/nt_asteroid_20x20.dmm +++ b/_maps/outpost/hangar/nt_asteroid_20x20.dmm @@ -370,7 +370,7 @@ }, /area/hangar) "jw" = ( -/obj/machinery/computer/cargo/express, +/obj/machinery/computer/cargo, /obj/structure/railing{ dir = 8; layer = 4.1 diff --git a/_maps/outpost/hangar/nt_asteroid_40x20.dmm b/_maps/outpost/hangar/nt_asteroid_40x20.dmm index b57c4972362c..312e0443aeea 100644 --- a/_maps/outpost/hangar/nt_asteroid_40x20.dmm +++ b/_maps/outpost/hangar/nt_asteroid_40x20.dmm @@ -839,7 +839,7 @@ }, /area/hangar) "tH" = ( -/obj/machinery/computer/cargo/express, +/obj/machinery/computer/cargo, /obj/item/toy/plush/knight{ pixel_y = 25; pixel_x = 9 diff --git a/_maps/outpost/hangar/nt_asteroid_40x40.dmm b/_maps/outpost/hangar/nt_asteroid_40x40.dmm index 48649aedf4d8..005b657e38ee 100644 --- a/_maps/outpost/hangar/nt_asteroid_40x40.dmm +++ b/_maps/outpost/hangar/nt_asteroid_40x40.dmm @@ -60,7 +60,7 @@ /obj/effect/turf_decal/techfloor{ dir = 4 }, -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8 }, /obj/machinery/light/directional/east, diff --git a/_maps/outpost/hangar/nt_asteroid_56x20.dmm b/_maps/outpost/hangar/nt_asteroid_56x20.dmm index 9dac115ca5e7..11ba5baac070 100644 --- a/_maps/outpost/hangar/nt_asteroid_56x20.dmm +++ b/_maps/outpost/hangar/nt_asteroid_56x20.dmm @@ -284,7 +284,7 @@ }, /area/hangar) "kx" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8; pixel_x = 7 }, diff --git a/_maps/outpost/hangar/nt_asteroid_56x40.dmm b/_maps/outpost/hangar/nt_asteroid_56x40.dmm index a3018e28aa32..5d66d8966d0b 100644 --- a/_maps/outpost/hangar/nt_asteroid_56x40.dmm +++ b/_maps/outpost/hangar/nt_asteroid_56x40.dmm @@ -723,7 +723,7 @@ }, /area/hangar) "Ed" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8; pixel_x = 7 }, diff --git a/_maps/outpost/nanotrasen_asteroid.dmm b/_maps/outpost/nanotrasen_asteroid.dmm index d1a184d736fc..816befea0002 100644 --- a/_maps/outpost/nanotrasen_asteroid.dmm +++ b/_maps/outpost/nanotrasen_asteroid.dmm @@ -5585,7 +5585,7 @@ /turf/open/floor/concrete/reinforced, /area/outpost/maintenance/aft) "tW" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8 }, /obj/effect/turf_decal/techfloor{ diff --git a/_maps/shuttles/independent/independent_beluga.dmm b/_maps/shuttles/independent/independent_beluga.dmm index 1eae63fcac48..c8ef49a3b35e 100644 --- a/_maps/shuttles/independent/independent_beluga.dmm +++ b/_maps/shuttles/independent/independent_beluga.dmm @@ -4742,7 +4742,7 @@ /area/ship/crew) "UO" = ( /obj/effect/turf_decal/industrial/traffic/corner, -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 1 }, /obj/machinery/light/directional/south, diff --git a/_maps/shuttles/independent/independent_box.dmm b/_maps/shuttles/independent/independent_box.dmm index 0e1e4e9439b5..577290c6581c 100644 --- a/_maps/shuttles/independent/independent_box.dmm +++ b/_maps/shuttles/independent/independent_box.dmm @@ -1802,7 +1802,7 @@ /obj/effect/turf_decal/corner/opaque/blue{ dir = 4 }, -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 1 }, /obj/machinery/firealarm/directional/south, diff --git a/_maps/shuttles/independent/independent_bubble.dmm b/_maps/shuttles/independent/independent_bubble.dmm index c34ad8349987..08fd116f2536 100644 --- a/_maps/shuttles/independent/independent_bubble.dmm +++ b/_maps/shuttles/independent/independent_bubble.dmm @@ -1164,7 +1164,7 @@ }, /obj/item/circuitboard/computer/selling_pad_control, /obj/item/circuitboard/machine/selling_pad, -/obj/item/circuitboard/computer/cargo/express, +/obj/item/circuitboard/computer/cargo, /obj/structure/closet/crate/engineering, /turf/open/floor/plasteel, /area/ship/cargo) diff --git a/_maps/shuttles/independent/independent_dwayne.dmm b/_maps/shuttles/independent/independent_dwayne.dmm index ef1435cb1558..668e1e164530 100644 --- a/_maps/shuttles/independent/independent_dwayne.dmm +++ b/_maps/shuttles/independent/independent_dwayne.dmm @@ -1974,7 +1974,7 @@ /obj/effect/turf_decal/corner/opaque/blue/half{ dir = 4 }, -/obj/machinery/computer/cargo/express/retro{ +/obj/machinery/computer/cargo/retro{ dir = 8 }, /turf/open/floor/plasteel/dark, diff --git a/_maps/shuttles/independent/independent_junker.dmm b/_maps/shuttles/independent/independent_junker.dmm index a5b4354e7456..136e6e6e17fb 100644 --- a/_maps/shuttles/independent/independent_junker.dmm +++ b/_maps/shuttles/independent/independent_junker.dmm @@ -2277,7 +2277,7 @@ }, /obj/effect/decal/cleanable/glass, /obj/structure/safe/floor, -/obj/item/circuitboard/computer/cargo/express, +/obj/item/circuitboard/computer/cargo, /turf/open/floor/pod/dark, /area/ship/crew/office) "Rj" = ( diff --git a/_maps/shuttles/independent/independent_kilo.dmm b/_maps/shuttles/independent/independent_kilo.dmm index a4c390afde8d..0f1f92a475c8 100644 --- a/_maps/shuttles/independent/independent_kilo.dmm +++ b/_maps/shuttles/independent/independent_kilo.dmm @@ -1252,7 +1252,7 @@ /area/ship/crew) "sW" = ( /obj/effect/turf_decal/industrial/outline/yellow, -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8 }, /obj/machinery/airalarm/directional/east, diff --git a/_maps/shuttles/independent/independent_lagoon.dmm b/_maps/shuttles/independent/independent_lagoon.dmm index 14823f92db63..77b0d605e91b 100644 --- a/_maps/shuttles/independent/independent_lagoon.dmm +++ b/_maps/shuttles/independent/independent_lagoon.dmm @@ -256,7 +256,7 @@ /turf/open/floor/plasteel, /area/ship/external) "bt" = ( -/obj/machinery/computer/cargo/express/retro{ +/obj/machinery/computer/cargo/retro{ dir = 4 }, /turf/open/floor/plasteel/patterned/cargo_one, diff --git a/_maps/shuttles/independent/independent_mudskipper.dmm b/_maps/shuttles/independent/independent_mudskipper.dmm index f82cdc7ba748..d7a3341b8927 100644 --- a/_maps/shuttles/independent/independent_mudskipper.dmm +++ b/_maps/shuttles/independent/independent_mudskipper.dmm @@ -913,7 +913,7 @@ /obj/structure/sign/warning/incident{ pixel_x = -32 }, -/obj/machinery/computer/cargo/express/retro{ +/obj/machinery/computer/cargo/retro{ dir = 4 }, /turf/open/floor/plasteel/tech/grid, diff --git a/_maps/shuttles/independent/independent_rigger.dmm b/_maps/shuttles/independent/independent_rigger.dmm index daf3cf9ecdb3..42a9f999f3f7 100644 --- a/_maps/shuttles/independent/independent_rigger.dmm +++ b/_maps/shuttles/independent/independent_rigger.dmm @@ -2231,7 +2231,7 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer2{ dir = 4 }, -/obj/machinery/computer/cargo/express, +/obj/machinery/computer/cargo, /obj/item/radio/intercom/directional/north, /turf/open/floor/carpet/blue, /area/ship/bridge) diff --git a/_maps/shuttles/independent/independent_schmiedeberg.dmm b/_maps/shuttles/independent/independent_schmiedeberg.dmm index 454e7503cb52..ce7b407a4731 100644 --- a/_maps/shuttles/independent/independent_schmiedeberg.dmm +++ b/_maps/shuttles/independent/independent_schmiedeberg.dmm @@ -756,7 +756,7 @@ /turf/open/floor/wood/walnut, /area/ship/crew/canteen) "ka" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 1 }, /obj/item/radio/intercom/directional/south, diff --git a/_maps/shuttles/independent/independent_shetland.dmm b/_maps/shuttles/independent/independent_shetland.dmm index e269c70cfefa..f147aeb82276 100644 --- a/_maps/shuttles/independent/independent_shetland.dmm +++ b/_maps/shuttles/independent/independent_shetland.dmm @@ -5464,7 +5464,7 @@ /obj/effect/turf_decal/corner/opaque/neutral/three_quarters{ dir = 1 }, -/obj/machinery/computer/cargo/express/retro, +/obj/machinery/computer/cargo/retro, /turf/open/floor/plasteel/telecomms_floor, /area/ship/bridge) "VD" = ( diff --git a/_maps/shuttles/independent/independent_sunskipper.dmm b/_maps/shuttles/independent/independent_sunskipper.dmm index 61c49a25295e..de92179a11f7 100644 --- a/_maps/shuttles/independent/independent_sunskipper.dmm +++ b/_maps/shuttles/independent/independent_sunskipper.dmm @@ -1560,6 +1560,9 @@ /obj/structure/cable/green{ icon_state = "4-9" }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ + dir = 8 + }, /turf/open/floor/carpet/nanoweave, /area/ship/crew/cryo) "tP" = ( @@ -2047,7 +2050,7 @@ /turf/open/floor/plasteel/tech, /area/ship/cargo) "AP" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ icon_state = "computer-right"; dir = 8 }, diff --git a/_maps/shuttles/inteq/inteq_colossus.dmm b/_maps/shuttles/inteq/inteq_colossus.dmm index 870a12949973..5925b9c0acdd 100644 --- a/_maps/shuttles/inteq/inteq_colossus.dmm +++ b/_maps/shuttles/inteq/inteq_colossus.dmm @@ -852,7 +852,7 @@ /area/ship/hallway/fore) "iX" = ( /obj/item/radio/intercom/wideband/directional/south, -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 1 }, /obj/effect/turf_decal/borderfloor, diff --git a/_maps/shuttles/inteq/inteq_hound.dmm b/_maps/shuttles/inteq/inteq_hound.dmm index 5616d1d2d4b0..da82ccbf26b7 100644 --- a/_maps/shuttles/inteq/inteq_hound.dmm +++ b/_maps/shuttles/inteq/inteq_hound.dmm @@ -1580,7 +1580,7 @@ dir = 1 }, /obj/effect/turf_decal/steeldecal/steel_decals_central4, -/obj/machinery/computer/cargo/express, +/obj/machinery/computer/cargo, /obj/item/radio/intercom/wideband/directional/north{ pixel_y = 25; pixel_x = 6 diff --git a/_maps/shuttles/inteq/inteq_talos.dmm b/_maps/shuttles/inteq/inteq_talos.dmm index 7a4a3bec6618..491853b5266c 100644 --- a/_maps/shuttles/inteq/inteq_talos.dmm +++ b/_maps/shuttles/inteq/inteq_talos.dmm @@ -2329,7 +2329,7 @@ /turf/open/floor/plasteel/tech, /area/ship/security/armory) "os" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8 }, /obj/effect/turf_decal/corner/opaque/brown{ diff --git a/_maps/shuttles/inteq/inteq_valor.dmm b/_maps/shuttles/inteq/inteq_valor.dmm index 1d0c4910e49e..0b41578dd31b 100644 --- a/_maps/shuttles/inteq/inteq_valor.dmm +++ b/_maps/shuttles/inteq/inteq_valor.dmm @@ -3855,7 +3855,7 @@ /turf/open/floor/plasteel/patterned, /area/ship/cargo) "Ko" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 1 }, /obj/effect/turf_decal/corner/opaque/brown{ diff --git a/_maps/shuttles/inteq/inteq_vaquero.dmm b/_maps/shuttles/inteq/inteq_vaquero.dmm index 23a80717b42f..9e8f7d6c81f5 100644 --- a/_maps/shuttles/inteq/inteq_vaquero.dmm +++ b/_maps/shuttles/inteq/inteq_vaquero.dmm @@ -2897,7 +2897,7 @@ /turf/open/floor/plasteel/tech, /area/ship/cargo) "TK" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8 }, /obj/effect/turf_decal/corner/opaque/yellow, diff --git a/_maps/shuttles/nanotrasen/nanotrasen_delta.dmm b/_maps/shuttles/nanotrasen/nanotrasen_delta.dmm index b723b020aa36..e5890b401cfa 100644 --- a/_maps/shuttles/nanotrasen/nanotrasen_delta.dmm +++ b/_maps/shuttles/nanotrasen/nanotrasen_delta.dmm @@ -2530,7 +2530,7 @@ /turf/open/floor/plasteel/dark, /area/ship/bridge) "Lv" = ( -/obj/machinery/computer/cargo/express/retro{ +/obj/machinery/computer/cargo/retro{ dir = 8 }, /obj/effect/turf_decal/corner/opaque/nsorange, diff --git a/_maps/shuttles/nanotrasen/nanotrasen_gecko.dmm b/_maps/shuttles/nanotrasen/nanotrasen_gecko.dmm index b05fd520c158..351f188e3369 100644 --- a/_maps/shuttles/nanotrasen/nanotrasen_gecko.dmm +++ b/_maps/shuttles/nanotrasen/nanotrasen_gecko.dmm @@ -4283,7 +4283,7 @@ /turf/open/floor/plasteel/grimy, /area/ship/crew) "RK" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 4 }, /obj/item/radio/intercom/directional/west, diff --git a/_maps/shuttles/nanotrasen/nanotrasen_heron.dmm b/_maps/shuttles/nanotrasen/nanotrasen_heron.dmm index b92747f3a3e2..0a0c9dead99f 100644 --- a/_maps/shuttles/nanotrasen/nanotrasen_heron.dmm +++ b/_maps/shuttles/nanotrasen/nanotrasen_heron.dmm @@ -10099,7 +10099,7 @@ /turf/open/floor/plasteel/tech, /area/ship/engineering) "LS" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8 }, /obj/structure/railing{ diff --git a/_maps/shuttles/nanotrasen/nanotrasen_meta.dmm b/_maps/shuttles/nanotrasen/nanotrasen_meta.dmm index 9abfe4c6c6cb..663a567b8bbc 100644 --- a/_maps/shuttles/nanotrasen/nanotrasen_meta.dmm +++ b/_maps/shuttles/nanotrasen/nanotrasen_meta.dmm @@ -1107,7 +1107,7 @@ /turf/open/floor/plasteel/dark, /area/ship/cargo) "dg" = ( -/obj/machinery/computer/cargo/express/retro{ +/obj/machinery/computer/cargo/retro{ dir = 8 }, /obj/effect/turf_decal/corner/opaque/blue/three_quarters{ @@ -2647,7 +2647,7 @@ /area/ship/cargo) "Du" = ( /obj/effect/turf_decal/corner/transparent/neutral/full, -/obj/machinery/computer/cargo/express/retro{ +/obj/machinery/computer/cargo/retro{ dir = 8 }, /obj/effect/decal/cleanable/dirt/dust, diff --git a/_maps/shuttles/nanotrasen/nanotrasen_mimir.dmm b/_maps/shuttles/nanotrasen/nanotrasen_mimir.dmm index f5ffea852281..928fc6bd90ee 100644 --- a/_maps/shuttles/nanotrasen/nanotrasen_mimir.dmm +++ b/_maps/shuttles/nanotrasen/nanotrasen_mimir.dmm @@ -4024,7 +4024,7 @@ /turf/open/floor/plasteel, /area/ship/security/prison) "xT" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8 }, /turf/open/floor/plasteel/telecomms_floor, diff --git a/_maps/shuttles/nanotrasen/nanotrasen_osprey.dmm b/_maps/shuttles/nanotrasen/nanotrasen_osprey.dmm index 774f1d57cc40..0c860abb9e20 100644 --- a/_maps/shuttles/nanotrasen/nanotrasen_osprey.dmm +++ b/_maps/shuttles/nanotrasen/nanotrasen_osprey.dmm @@ -95,7 +95,7 @@ /obj/structure/disposalpipe/segment{ dir = 8 }, -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8 }, /obj/effect/turf_decal/corner/opaque/brown{ diff --git a/_maps/shuttles/nanotrasen/nanotrasen_ranger.dmm b/_maps/shuttles/nanotrasen/nanotrasen_ranger.dmm index a106a307bb18..342ffb8fa928 100644 --- a/_maps/shuttles/nanotrasen/nanotrasen_ranger.dmm +++ b/_maps/shuttles/nanotrasen/nanotrasen_ranger.dmm @@ -464,7 +464,7 @@ /turf/open/floor/plasteel/white, /area/ship/hallway/port) "eE" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 1 }, /turf/open/floor/plasteel/tech, diff --git a/_maps/shuttles/nanotrasen/nanotrasen_skipper.dmm b/_maps/shuttles/nanotrasen/nanotrasen_skipper.dmm index f910af5043c8..f9aeea662f05 100644 --- a/_maps/shuttles/nanotrasen/nanotrasen_skipper.dmm +++ b/_maps/shuttles/nanotrasen/nanotrasen_skipper.dmm @@ -4235,7 +4235,7 @@ "JA" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 1 }, /turf/open/floor/plasteel/dark, diff --git a/_maps/shuttles/pgf/pgf_crying_sun.dmm b/_maps/shuttles/pgf/pgf_crying_sun.dmm index 919770509bec..e016ef725525 100644 --- a/_maps/shuttles/pgf/pgf_crying_sun.dmm +++ b/_maps/shuttles/pgf/pgf_crying_sun.dmm @@ -464,7 +464,7 @@ /turf/open/floor/plasteel/telecomms_floor, /area/ship/hallway/port) "dK" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8 }, /obj/structure/catwalk/over/plated_catwalk/dark, diff --git a/_maps/shuttles/roumain/srm_elder.dmm b/_maps/shuttles/roumain/srm_elder.dmm index e4a85560cb67..5ef138ad19db 100644 --- a/_maps/shuttles/roumain/srm_elder.dmm +++ b/_maps/shuttles/roumain/srm_elder.dmm @@ -3609,7 +3609,7 @@ /turf/open/floor/wood/maple, /area/ship/crew/cryo) "Sg" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8 }, /obj/effect/turf_decal/spline/fancy/wood{ diff --git a/_maps/shuttles/solgov/solgov_chronicle.dmm b/_maps/shuttles/solgov/solgov_chronicle.dmm index 13e78929b4dc..012261bda246 100644 --- a/_maps/shuttles/solgov/solgov_chronicle.dmm +++ b/_maps/shuttles/solgov/solgov_chronicle.dmm @@ -350,7 +350,7 @@ /turf/open/floor/wood, /area/ship/crew) "da" = ( -/obj/machinery/computer/cargo/express/solgov{ +/obj/machinery/computer/cargo/solgov{ dir = 4 }, /obj/item/radio/intercom/directional/west, diff --git a/_maps/shuttles/solgov/solgov_inkwell.dmm b/_maps/shuttles/solgov/solgov_inkwell.dmm index da2a6b032eaa..86781cc2e251 100644 --- a/_maps/shuttles/solgov/solgov_inkwell.dmm +++ b/_maps/shuttles/solgov/solgov_inkwell.dmm @@ -2139,7 +2139,7 @@ /turf/open/floor/plasteel/mono, /area/ship/cargo) "nO" = ( -/obj/machinery/computer/cargo/express/solgov, +/obj/machinery/computer/cargo/solgov, /turf/open/floor/wood/maple, /area/ship/bridge) "nR" = ( diff --git a/_maps/shuttles/solgov/solgov_paracelsus.dmm b/_maps/shuttles/solgov/solgov_paracelsus.dmm index b099e500aee9..1235af6da913 100644 --- a/_maps/shuttles/solgov/solgov_paracelsus.dmm +++ b/_maps/shuttles/solgov/solgov_paracelsus.dmm @@ -2725,7 +2725,7 @@ /obj/structure/railing/wood{ dir = 8 }, -/obj/machinery/computer/cargo/express/solgov{ +/obj/machinery/computer/cargo/solgov{ dir = 4 }, /obj/effect/turf_decal/siding/wood{ diff --git a/_maps/shuttles/syndicate/syndicate_cybersun_kansatsu.dmm b/_maps/shuttles/syndicate/syndicate_cybersun_kansatsu.dmm index 41faf816d827..ffc2472b5dec 100644 --- a/_maps/shuttles/syndicate/syndicate_cybersun_kansatsu.dmm +++ b/_maps/shuttles/syndicate/syndicate_cybersun_kansatsu.dmm @@ -258,7 +258,7 @@ /turf/open/floor/plasteel/stairs, /area/ship/cargo) "fk" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8 }, /obj/machinery/button/door{ diff --git a/_maps/shuttles/syndicate/syndicate_gorlex_hyena.dmm b/_maps/shuttles/syndicate/syndicate_gorlex_hyena.dmm index 7c7a34fd2690..ae46dc0286f3 100644 --- a/_maps/shuttles/syndicate/syndicate_gorlex_hyena.dmm +++ b/_maps/shuttles/syndicate/syndicate_gorlex_hyena.dmm @@ -952,7 +952,7 @@ "pI" = ( /obj/item/radio/intercom/wideband/directional/east, /obj/effect/decal/cleanable/dirt/dust, -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 1 }, /obj/effect/turf_decal/borderfloorblack, diff --git a/_maps/shuttles/syndicate/syndicate_gorlex_komodo.dmm b/_maps/shuttles/syndicate/syndicate_gorlex_komodo.dmm index 7c323e43dbe0..bfbdc4e43e04 100644 --- a/_maps/shuttles/syndicate/syndicate_gorlex_komodo.dmm +++ b/_maps/shuttles/syndicate/syndicate_gorlex_komodo.dmm @@ -3507,7 +3507,7 @@ /turf/open/floor/mineral/plastitanium/red, /area/ship/hallway/central) "HI" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ layer = 3 }, /obj/effect/turf_decal/techfloor{ diff --git a/_maps/shuttles/syndicate/syndicate_litieguai.dmm b/_maps/shuttles/syndicate/syndicate_litieguai.dmm index c2e92f15f167..09ad85bc606f 100644 --- a/_maps/shuttles/syndicate/syndicate_litieguai.dmm +++ b/_maps/shuttles/syndicate/syndicate_litieguai.dmm @@ -2608,7 +2608,7 @@ /turf/open/floor/plasteel/white, /area/ship/hallway/central) "TA" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8 }, /turf/open/floor/plasteel/dark, diff --git a/_maps/shuttles/syndicate/syndicate_panacea.dmm b/_maps/shuttles/syndicate/syndicate_panacea.dmm index a55e39dd9e27..702798048e53 100644 --- a/_maps/shuttles/syndicate/syndicate_panacea.dmm +++ b/_maps/shuttles/syndicate/syndicate_panacea.dmm @@ -887,7 +887,7 @@ /turf/open/floor/suns/dark/plain, /area/ship/crew/office/lobby) "fG" = ( -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8 }, /turf/open/floor/suns/dark, diff --git a/_maps/shuttles/syndicate/syndicate_twinkleshine.dmm b/_maps/shuttles/syndicate/syndicate_twinkleshine.dmm index 9967d69f6d07..1adef58948fe 100644 --- a/_maps/shuttles/syndicate/syndicate_twinkleshine.dmm +++ b/_maps/shuttles/syndicate/syndicate_twinkleshine.dmm @@ -1580,7 +1580,7 @@ /obj/effect/turf_decal/corner/opaque/syndiered/half{ dir = 4 }, -/obj/machinery/computer/cargo/express{ +/obj/machinery/computer/cargo{ dir = 8; icon_state = "computer-left" }, diff --git a/check_regex.yaml b/check_regex.yaml index d03e15391975..441f1e44d743 100644 --- a/check_regex.yaml +++ b/check_regex.yaml @@ -31,14 +31,14 @@ standards: - exactly: [4, "/mob text paths", '"/mob'] - exactly: [43, "/obj text paths", '"/obj'] - exactly: [0, "/turf text paths", '"/turf'] - - exactly: [117, "text2path uses", "text2path"] + - exactly: [116, "text2path uses", "text2path"] - exactly: [18, "world<< uses", 'world[ \t]*<<'] - exactly: [0, "world.log<< uses", 'world.log[ \t]*<<'] - exactly: [ - 265, + 266, "non-bitwise << uses", '(?- -#define AMMO_BOX_PER_BULLET 1 -///ammo box will have a different state for full and empty; -max_ammo and -0 -#define AMMO_BOX_FULL_EMPTY 2 - -#define SUPPRESSED_NONE 0 -#define SUPPRESSED_QUIET 1 ///standard suppressed -#define SUPPRESSED_VERY 2 /// no message - //Autofire component /// Compatible firemode is in the gun. Wait until it's held in the user hands. #define AUTOFIRE_STAT_IDLE (1<<0) @@ -54,6 +43,10 @@ #define COMSIG_AUTOFIRE_SHOT "autofire_shot" #define COMPONENT_AUTOFIRE_SHOT_SUCCESS (1<<0) +#define SUPPRESSED_NONE 0 +#define SUPPRESSED_QUIET 1 ///standard suppressed +#define SUPPRESSED_VERY 2 /// no message + #define DUALWIELD_PENALTY_EXTRA_MULTIPLIER 1.6 #define MANUFACTURER_NONE null @@ -72,6 +65,69 @@ #define MANUFACTURER_PGF "the Etherbor Industries emblem" #define MANUFACTURER_IMPORT "Lanchester Import Co." +///////////////// +// ATTACHMENTS // +///////////////// +#define TRAIT_ATTACHABLE "attachable" + +#define COMSIG_ATTACHMENT_ATTACH "attach-attach" +#define COMSIG_ATTACHMENT_DETACH "attach-detach" +#define COMSIG_ATTACHMENT_EXAMINE "attach-examine" +#define COMSIG_ATTACHMENT_EXAMINE_MORE "attach-examine-more" +#define COMSIG_ATTACHMENT_PRE_ATTACK "attach-pre-attack" +#define COMSIG_ATTACHMENT_ATTACK "attach-attacked" +#define COMSIG_ATTACHMENT_UPDATE_OVERLAY "attach-overlay" + +#define COMSIG_ATTACHMENT_TOGGLE "attach-toggle" + +#define COMSIG_ATTACHMENT_GET_SLOT "attach-slot-who" +#define ATTACHMENT_SLOT_MUZZLE "muzzle" +#define ATTACHMENT_SLOT_SCOPE "scope" +#define ATTACHMENT_SLOT_GRIP "grip" +#define ATTACHMENT_SLOT_RAIL "rail" +#define ATTACHMENT_SLOT_STOCK "stock" + +/proc/attachment_slot_to_bflag(slot) + switch(slot) + if(ATTACHMENT_SLOT_MUZZLE) + return (1<<0) + if(ATTACHMENT_SLOT_SCOPE) + return (1<<1) + if(ATTACHMENT_SLOT_GRIP) + return (1<<2) + if(ATTACHMENT_SLOT_RAIL) + return (1<<3) + if(ATTACHMENT_SLOT_STOCK) + return (1<<4) + +/proc/attachment_slot_from_bflag(slot) + switch(slot) + if(1<<0) + return ATTACHMENT_SLOT_MUZZLE + if(1<<1) + return ATTACHMENT_SLOT_SCOPE + if(1<<2) + return ATTACHMENT_SLOT_GRIP + if(1<<3) + return ATTACHMENT_SLOT_RAIL + if(1<<4) + return ATTACHMENT_SLOT_STOCK + +#define ATTACHMENT_DEFAULT_SLOT_AVAILABLE list( \ + ATTACHMENT_SLOT_MUZZLE = 1, \ + ATTACHMENT_SLOT_SCOPE = 1, \ + ATTACHMENT_SLOT_GRIP = 1, \ + ATTACHMENT_SLOT_RAIL = 1, \ + ATTACHMENT_SLOT_STOCK = 1, \ +) + +//attach_features_flags +/// Removable by hand +#define ATTACH_REMOVABLE_HAND (1<<0) +/// Removable via crowbar +#define ATTACH_REMOVABLE_TOOL (1<<1) +#define ATTACH_TOGGLE (1<<2) +#define ATTACH_NO_SPRITE (1<<3) ///////////////// // PROJECTILES // @@ -84,6 +140,18 @@ #define NICE_SHOT_RICOCHET_BONUS 10 //if the shooter has the NICE_SHOT trait and they fire a ricocheting projectile, add this to the ricochet chance and auto aim angle +//ammo box sprite defines +///ammo box will always use provided icon state +#define AMMO_BOX_ONE_SPRITE 0 +///ammo box will have a different state for each bullet; - +#define AMMO_BOX_PER_BULLET 1 +///ammo box will have a different state for full and empty; -max_ammo and -0 +#define AMMO_BOX_FULL_EMPTY 2 + +#define MAG_SIZE_SMALL 1 +#define MAG_SIZE_MEDIUM 2 +#define MAG_SIZE_LARGE 3 + //Projectile Reflect #define REFLECT_NORMAL (1<<0) #define REFLECT_FAKEPROJECTILE (1<<1) @@ -96,3 +164,6 @@ #define FIREMODE_FULLAUTO "auto" #define FIREMODE_OTHER "other" #define FIREMODE_OTHER_TWO "other2" + +#define GUN_LEFTHAND_ICON 'icons/mob/inhands/weapons/guns_lefthand.dmi' +#define GUN_RIGHTHAND_ICON 'icons/mob/inhands/weapons/guns_righthand.dmi' diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm index eaf26367b54d..285e7ce5ff80 100644 --- a/code/__DEFINES/sound.dm +++ b/code/__DEFINES/sound.dm @@ -205,3 +205,5 @@ #define SFX_CRUNCHY_BUSH_WHACK "crunchy_bush_whack" #define SFX_TREE_CHOP "tree_chop" #define SFX_ROCK_TAP "rock_tap" + +#define SOUND_EMPTY_MAG 'sound/weapons/empty.ogg' diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index c8c7b63d0a09..d6b048de4289 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -295,7 +295,7 @@ Turf and target are separate in case you want to teleport some distance from a t return "[pick("!","@","#","$","%","^","&")][pick("!","@","#","$","%","^","&","*")][pick("!","@","#","$","%","^","&","*")][pick("!","@","#","$","%","^","&","*")]" //Returns a list of all items of interest with their name -/proc/getpois(mobs_only = FALSE, skip_mindless = FALSE, specify_dead_role = TRUE) +/proc/getpois(mobs_only = FALSE, skip_mindless = FALSE, specify_dead_role = TRUE, only_realname = FALSE) var/list/mobs = sortmobs() var/list/namecounts = list() var/list/pois = list() @@ -305,7 +305,11 @@ Turf and target are separate in case you want to teleport some distance from a t continue if(M.client && M.client.holder && M.client.holder.fakekey) //stealthmins continue - var/name = avoid_assoc_duplicate_keys(M.name, namecounts) + M.get_realname_string() + var/name = "" + if(only_realname) + name = avoid_assoc_duplicate_keys(M.real_name, namecounts) + else + name = avoid_assoc_duplicate_keys(M.name, namecounts) + M.get_realname_string() if(M.stat == DEAD && specify_dead_role) if(isobserver(M)) @@ -321,6 +325,7 @@ Turf and target are separate in case you want to teleport some distance from a t pois[avoid_assoc_duplicate_keys(A.name, namecounts)] = A return pois + //Orders mobs by type then by name /proc/sortmobs() var/list/moblist = list() diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 993026c0d5e0..a6f81d8ca4f1 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -366,7 +366,7 @@ return /atom/proc/CtrlShiftClick(mob/user) - SEND_SIGNAL(src, COMSIG_CLICK_CTRL_SHIFT) + SEND_SIGNAL(src, COMSIG_CLICK_CTRL_SHIFT, user) return /* diff --git a/code/datums/action.dm b/code/datums/action.dm index 9ceaf8bc9f6d..e8d0ea303888 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -81,9 +81,10 @@ if(owner) UnregisterSignal(owner, COMSIG_PARENT_QDELETING) owner = null - button.moved = FALSE //so the button appears in its normal position when given to another owner. - button.locked = FALSE - button.id = null + if(button) + button.moved = FALSE //so the button appears in its normal position when given to another owner. + button.locked = FALSE + button.id = null /datum/action/proc/Trigger(trigger_flags) if(!IsAvailable()) diff --git a/code/datums/components/attachment.dm b/code/datums/components/attachment.dm new file mode 100644 index 000000000000..01e3abedd80b --- /dev/null +++ b/code/datums/components/attachment.dm @@ -0,0 +1,182 @@ +/datum/component/attachment + ///Slot the attachment goes on, also used in descriptions so should be player readable + var/slot + ///various yes no flags associated with attachments. See defines for these: [_DEFINES/guns.dm] + var/attach_features_flags + ///Unused so far, should probally handle it in the parent unless you have a specific reason + var/list/valid_parent_types + var/datum/callback/on_attach + var/datum/callback/on_detach + var/datum/callback/on_toggle + ///Called on the parents preattack + var/datum/callback/on_preattack + ///Unused...Also a little broken.. + var/list/datum/action/actions + ///Generated if the attachment can toggle, sends COMSIG_ATTACHMENT_TOGGLE + var/datum/action/attachment/attachment_toggle_action + +/datum/component/attachment/Initialize( + slot = ATTACHMENT_SLOT_RAIL, + attach_features_flags = ATTACH_REMOVABLE_HAND, + valid_parent_types = list(/obj/item/gun), + datum/callback/on_attach = null, + datum/callback/on_detach = null, + datum/callback/on_toggle = null, + datum/callback/on_preattack = null, + list/signals = null + ) + + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + + src.slot = slot + src.attach_features_flags = attach_features_flags + src.valid_parent_types = valid_parent_types + src.on_attach = on_attach + src.on_detach = on_detach + src.on_toggle = on_toggle + src.on_preattack = on_preattack + + ADD_TRAIT(parent, TRAIT_ATTACHABLE, "attachable") + RegisterSignal(parent, COMSIG_ATTACHMENT_ATTACH, PROC_REF(try_attach)) + RegisterSignal(parent, COMSIG_ATTACHMENT_DETACH, PROC_REF(try_detach)) + RegisterSignal(parent, COMSIG_ATTACHMENT_EXAMINE, PROC_REF(handle_examine)) + RegisterSignal(parent, COMSIG_ATTACHMENT_EXAMINE_MORE, PROC_REF(handle_examine_more)) + if(attach_features_flags & ATTACH_TOGGLE) + RegisterSignal(parent, COMSIG_ATTACHMENT_TOGGLE, PROC_REF(try_toggle)) + attachment_toggle_action = new /datum/action/attachment(parent) + RegisterSignal(parent, COMSIG_ATTACHMENT_PRE_ATTACK, PROC_REF(relay_pre_attack)) + RegisterSignal(parent, COMSIG_ATTACHMENT_UPDATE_OVERLAY, PROC_REF(update_overlays)) + RegisterSignal(parent, COMSIG_ATTACHMENT_GET_SLOT, PROC_REF(send_slot)) + + for(var/signal in signals) + RegisterSignal(parent, signal, signals[signal]) + +/datum/component/attachment/Destroy(force, silent) + REMOVE_TRAIT(parent, TRAIT_ATTACHABLE, "attachable") + if(actions && length(actions)) + var/obj/item/gun/parent = src.parent + parent.actions -= actions + QDEL_LIST(actions) + qdel(attachment_toggle_action) + return ..() + +/datum/component/attachment/proc/try_toggle(obj/item/parent, obj/item/holder, mob/user) + SIGNAL_HANDLER + if(attach_features_flags & ATTACH_TOGGLE) + INVOKE_ASYNC(src, PROC_REF(do_toggle), parent, holder, user) + holder.update_icon() + attachment_toggle_action.UpdateButtonIcon() + +/datum/component/attachment/proc/do_toggle(obj/item/parent, obj/item/holder, mob/user) + if(on_toggle) + on_toggle.Invoke(holder, user) + return TRUE + + parent.attack_self(user) + return TRUE + +/datum/component/attachment/proc/update_overlays(obj/item/parent, list/overlays, list/offset) + if(!(attach_features_flags & ATTACH_NO_SPRITE)) + overlays += mutable_appearance(parent.icon, "[parent.icon_state]-attached") + +/datum/component/attachment/proc/try_attach(obj/item/parent, obj/item/holder, mob/user, bypass_checks) + SIGNAL_HANDLER + + if(!bypass_checks) + if(!parent.Adjacent(user) || (length(valid_parent_types) && (holder.type in valid_parent_types))) + return FALSE + + if(on_attach && !on_attach.Invoke(holder, user)) + return FALSE + + parent.forceMove(holder) + + if(attach_features_flags & ATTACH_TOGGLE) + holder.actions += list(attachment_toggle_action) + attachment_toggle_action.gun = holder + attachment_toggle_action.Grant(user) + + return TRUE + +/datum/component/attachment/proc/try_detach(obj/item/parent, obj/item/holder, mob/user) + SIGNAL_HANDLER + + if(!parent.Adjacent(user) || (valid_parent_types && (holder.type in valid_parent_types))) + return FALSE + + if(on_attach && !on_detach.Invoke(holder, user)) + return FALSE + + if(attach_features_flags & ATTACH_TOGGLE) + holder.actions -= list(attachment_toggle_action) + attachment_toggle_action.gun = null + attachment_toggle_action.Remove(user) + + if(user.can_put_in_hand(parent)) + user.put_in_hand(parent) + return TRUE + + parent.forceMove(holder.drop_location()) + return TRUE + +/datum/component/attachment/proc/handle_examine(obj/item/parent, mob/user, list/examine_list) + SIGNAL_HANDLER + +/datum/component/attachment/proc/handle_examine_more(obj/item/parent, mob/user, list/examine_list) + SIGNAL_HANDLER + +/datum/component/attachment/proc/relay_pre_attack(obj/item/parent, obj/item/gun, atom/target_atom, mob/user, params) + SIGNAL_HANDLER_DOES_SLEEP + + if(on_preattack) + return on_preattack.Invoke(gun, target_atom, user, params) + +/datum/component/attachment/proc/send_slot(obj/item/parent) + SIGNAL_HANDLER + return attachment_slot_to_bflag(slot) + +/datum/action/attachment + name = "Toggle Attachment" + check_flags = AB_CHECK_HANDS_BLOCKED|AB_CHECK_CONSCIOUS + button_icon_state = null + ///Decides where we send our toggle signal for when pressed + var/obj/item/gun/gun = null + +/datum/action/attachment/New(Target) + ..() + name = "Toggle [target.name]" + button.name = name + icon_icon = target.icon + button_icon_state = target.icon_state + +/datum/action/attachment/Destroy() + . = ..() + gun = null + +/datum/action/attachment/Trigger() + ..() + SEND_SIGNAL(target, COMSIG_ATTACHMENT_TOGGLE, gun, owner) + +/datum/action/attachment/UpdateButtonIcon() + icon_icon = target.icon + button_icon_state = target.icon_state + ..() + +//Copied from item action.. +/datum/action/attachment/ApplyIcon(atom/movable/screen/movable/action_button/current_button, force) + if(button_icon && button_icon_state) + // If set, use the custom icon that we set instead + // of the item appearence + ..() + else if((target && current_button.appearance_cache != target.appearance) || force) //replace with /ref comparison if this is not valid. + var/obj/item/I = target + var/old_layer = I.layer + var/old_plane = I.plane + I.layer = FLOAT_LAYER //AAAH + I.plane = FLOAT_PLANE //^ what that guy said + current_button.cut_overlays() + current_button.add_overlay(I) + I.layer = old_layer + I.plane = old_plane + current_button.appearance_cache = I.appearance diff --git a/code/datums/components/attachment_holder.dm b/code/datums/components/attachment_holder.dm new file mode 100644 index 000000000000..82968a17604b --- /dev/null +++ b/code/datums/components/attachment_holder.dm @@ -0,0 +1,188 @@ +/datum/component/attachment_holder + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + + ///List of things you can attach to the parent + var/list/valid_types = null + ///How many slots a parent can hold of any one slot + var/list/slot_room = null + ///Icon offsets, should match the sprite itself so just find the position where it should attach + var/list/slot_offsets = null + var/list/obj/item/attachments = list() + +/datum/component/attachment_holder/Initialize( + list/slot_room = null, + list/valid_types = null, + list/slot_offsets = null, + list/default_attachments = null + ) + + if(!isgun(parent)) + return COMPONENT_INCOMPATIBLE + var/obj/item/gun/parent_gun = parent + + src.slot_room = slot_room + src.valid_types = valid_types + src.slot_offsets = slot_offsets + + RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, PROC_REF(handle_attack)) + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(handle_examine)) + RegisterSignal(parent, COMSIG_PARENT_EXAMINE_MORE, PROC_REF(handle_examine_more)) + RegisterSignal(parent, COMSIG_PARENT_QDELETING, PROC_REF(handle_qdel)) + RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, PROC_REF(handle_item_pre_attack)) + RegisterSignal(parent, COMSIG_CLICK_CTRL_SHIFT, PROC_REF(handle_ctrl_shift_click)) + RegisterSignal(parent, COMSIG_CLICK_ALT, PROC_REF(handle_alt_click)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(handle_overlays)) + + if(length(default_attachments)) + for(var/attachment in default_attachments) + var/obj/item/attachment/new_attachment = new attachment(parent_gun.loc) + INVOKE_ASYNC(src, PROC_REF(do_attach), new_attachment, null, TRUE) + +/datum/component/attachment_holder/proc/handle_overlays(obj/item/parent, list/overlays) + SIGNAL_HANDLER + + for(var/obj/item/attachment/attach as anything in attachments) + var/slot = SEND_SIGNAL(attach, COMSIG_ATTACHMENT_GET_SLOT) + slot = attachment_slot_from_bflag(slot) + var/list/attach_overlays = list() + SEND_SIGNAL(attach, COMSIG_ATTACHMENT_UPDATE_OVERLAY, attach_overlays) + for(var/mutable_appearance/overlay as anything in attach_overlays) + if(slot_offsets && slot_offsets[slot]) + var/matrix/overlay_matrix = new + overlay_matrix.Translate(slot_offsets[slot]["x"] - attach.pixel_shift_x, slot_offsets[slot]["y"] - attach.pixel_shift_y) + overlay.transform = overlay_matrix + overlays += overlay + +/datum/component/attachment_holder/proc/handle_qdel() + SIGNAL_HANDLER + qdel(src) + +/datum/component/attachment_holder/Destroy(force, silent) + QDEL_LIST(attachments) + attachments = null + return ..() + +/datum/component/attachment_holder/proc/attachments_to_list(only_toggles = FALSE) + . = list() + for(var/obj/item/attachment/attach as anything in attachments) + if(attach.name in .) + stack_trace("two attachments with same name; this shouldn't happen and will cause failures") + continue + if(only_toggles && !(attach.attach_features_flags & ATTACH_TOGGLE)) + continue + .[attach.name] = attach + +/datum/component/attachment_holder/proc/handle_ctrl_shift_click(obj/item/parent, mob/user) + SIGNAL_HANDLER + + INVOKE_ASYNC(src, PROC_REF(do_attachment_radial), parent, user) + +/datum/component/attachment_holder/proc/handle_alt_click(obj/item/parent, mob/user) + SIGNAL_HANDLER + + INVOKE_ASYNC(src, PROC_REF(handle_detach), parent, user) + +/datum/component/attachment_holder/proc/do_attachment_radial(obj/item/parent, mob/user) + var/list/attachments_as_list = attachments_to_list(TRUE) + var/selection = show_radial_menu(user, parent, attachments_as_list) + var/obj/item/attach = attachments_as_list[selection] + if(!attach) + return + SEND_SIGNAL(attach, COMSIG_ATTACHMENT_TOGGLE, parent, user) + +/datum/component/attachment_holder/proc/handle_examine(obj/item/parent, mob/user, list/examine_list) + if(length(attachments)) + examine_list += span_notice("It has [length(attachments)] attachment\s.") + for(var/obj/item/attach as anything in attachments) + SEND_SIGNAL(attach, COMSIG_ATTACHMENT_EXAMINE, user, examine_list) + +/datum/component/attachment_holder/proc/handle_examine_more(obj/item/parent, mob/user, list/examine_list) + for(var/key in slot_room) + if(slot_room[key]) + examine_list += span_notice("It has [slot_room[key]] slot\s free for [key] attachments.") + if(length(attachments)) + examine_list += span_notice("It has the following attachments:") + for(var/obj/item/attach as anything in attachments) + examine_list += span_notice("\t- [attach.name]") + if(length(valid_types)) + examine_list += span_notice("It can accept:") + for(var/obj/attach_type as anything in valid_types) + examine_list += span_notice("\t- [initial(attach_type.name)]") + for(var/obj/item/attach as anything in attachments) + SEND_SIGNAL(attach, COMSIG_ATTACHMENT_EXAMINE_MORE, user, examine_list) + +/datum/component/attachment_holder/proc/do_attach(obj/item/attachment, mob/user, bypass_checks) + var/slot = SEND_SIGNAL(attachment, COMSIG_ATTACHMENT_GET_SLOT) + slot = attachment_slot_from_bflag(slot) + if(!(attachment.type in valid_types)) + to_chat(user, span_notice("[attachment] is not a valid attachment for this [parent]!")) + return + if(!slot_room[slot]) + to_chat(user, span_notice("[parent] does not contain room for [attachment]!")) + return + slot_room[slot]-- + . = SEND_SIGNAL(attachment, COMSIG_ATTACHMENT_ATTACH, parent, user, bypass_checks) + if(.) + attachments += attachment + var/atom/parent = src.parent + parent.update_icon() + +/datum/component/attachment_holder/proc/do_detach(obj/item/attachment, mob/user) + var/slot = SEND_SIGNAL(attachment, COMSIG_ATTACHMENT_GET_SLOT) + slot = attachment_slot_from_bflag(slot) + if(slot in slot_room) + slot_room[slot]++ + . = SEND_SIGNAL(attachment, COMSIG_ATTACHMENT_DETACH, parent, user) + if(.) + attachments -= attachment + var/atom/parent = src.parent + parent.update_icon() + +/datum/component/attachment_holder/proc/handle_detach(obj/item/parent, mob/user, obj/item/tool) + var/list/tool_list = list() + var/list/hand_list = list() + for(var/obj/item/attachment/attach as anything in attachments) + if(attach.attach_features_flags & ATTACH_REMOVABLE_TOOL) + tool_list[attach.name] = attach + if(attach.attach_features_flags & ATTACH_REMOVABLE_HAND) + hand_list[attach.name] = attach + if(tool) + if(!length(tool_list)) + return + var/selected = tgui_input_list(user, "Select Attachment", "Detach", tool_list) + if(!parent.Adjacent(user) || !selected || !tool || !tool.use_tool(parent, user, 2 SECONDS * tool.toolspeed)) + return + do_detach(tool_list[selected], user) + else + if(!length(hand_list)) + return + var/selected = tgui_input_list(user, "Select Attachment", "Detach", hand_list) + if(do_after(user, 2 SECONDS, parent)) + do_detach(hand_list[selected], user) + + +/datum/component/attachment_holder/proc/handle_attack(obj/item/parent, obj/item/item, mob/user) + SIGNAL_HANDLER + + if(!user.Adjacent(parent)) + return + + if(item.tool_behaviour == TOOL_CROWBAR && length(attachments)) + INVOKE_ASYNC(src, PROC_REF(handle_detach), parent, user, item) + return TRUE + + if(HAS_TRAIT(item, TRAIT_ATTACHABLE)) + INVOKE_ASYNC(src, PROC_REF(do_attach), item, user) + return TRUE + + for(var/obj/item/attach as anything in attachments) + if(SEND_SIGNAL(attach, COMSIG_ATTACHMENT_ATTACK, parent, item, user)) + parent.update_icon() + return TRUE + +/datum/component/attachment_holder/proc/handle_item_pre_attack(obj/item/parent, atom/target_atom, mob/user, params) + SIGNAL_HANDLER + + for(var/obj/item/attach as anything in attachments) + if(SEND_SIGNAL(attach, COMSIG_ATTACHMENT_PRE_ATTACK, parent, target_atom, user, params)) + return TRUE diff --git a/code/datums/wires/mines.dm b/code/datums/wires/mines.dm index 4c856cf99d3f..91e0ac816189 100644 --- a/code/datums/wires/mines.dm +++ b/code/datums/wires/mines.dm @@ -28,7 +28,7 @@ if(WIRE_PIN) if(ourmine.clicked == TRUE) holder.visible_message(span_notice("[icon2html(ourmine, viewers(holder))] You hear something inside \the [ourmine] click softly.")) - playsound(ourmine, 'sound/weapons/empty.ogg', 30, TRUE) + playsound(ourmine, SOUND_EMPTY_MAG, 30, TRUE) ourmine.clicked = FALSE else holder.visible_message(span_notice("[icon2html(ourmine, viewers(holder))] \The [ourmine]'s detonation pad shifts slightly. Nothing happens.")) @@ -61,7 +61,7 @@ ourmine.dud = TRUE if(ourmine.clicked == TRUE) holder.visible_message(span_notice("[icon2html(ourmine, viewers(holder))] You hear something inside \the [ourmine] shift out of place.")) - playsound(ourmine, 'sound/weapons/empty.ogg', 30, TRUE) + playsound(ourmine, SOUND_EMPTY_MAG, 30, TRUE) ourmine.clicked = FALSE else holder.visible_message(span_notice("[icon2html(ourmine, viewers(holder))] \The [ourmine]'s detonation pad goes loose.")) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index e355c72e5569..cd00f4b88e08 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1595,6 +1595,15 @@ if(istype(ship)) var/obj/docking_port/mobile/shuttle = ship.mobile_port if(shuttle) + if(istype(shuttle.docked, /obj/docking_port/stationary)) + var/obj/docking_port/stationary/shipfinder = shuttle.docked + if(shipfinder.owner_ship) + for(var/datum/weakref/weakref as anything in shipfinder.owner_ship.gravgen_list) + var/obj/machinery/power/ship_gravity/SG = weakref.resolve() + if(!SG) + shipfinder.owner_ship.gravgen_list -= weakref + continue + max_grav = max(SG.active,max_grav) for(var/datum/weakref/weakref as anything in shuttle.gravgen_list) var/obj/machinery/power/ship_gravity/SG = weakref.resolve() if(!SG) diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index 4a16a6f9b249..b0b40ea0877e 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -6,7 +6,7 @@ var/fire_sound var/projectiles_per_shot = 1 var/variance = 0 - var/randomspread = 0 //use random spread for machineguns, instead of shotgun scatter + var/randomspread = FALSE //use random spread for machineguns, instead of shotgun scatter var/projectile_delay = 0 var/firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect //the visual effect appearing when the weapon is fired. var/kickback = TRUE //Will using this weapon in no grav push mecha back. @@ -137,8 +137,8 @@ desc = "A device that shoots resonant plasma bursts at extreme velocity. The blasts are capable of crushing rock and demolishing solid obstacles." icon_state = "mecha_plasmacutter" item_state = "plasmacutter" - lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + lefthand_file = GUN_LEFTHAND_ICON + righthand_file = GUN_RIGHTHAND_ICON energy_drain = 30 projectile = /obj/projectile/plasma/adv/mech fire_sound = 'sound/weapons/plasma_cutter.ogg' @@ -347,7 +347,7 @@ projectiles_cache_max = 1200 projectiles_per_shot = 3 variance = 6 - randomspread = 1 + randomspread = TRUE projectile_delay = 2 harmful = TRUE ammo_type = "lmg" diff --git a/code/game/objects/items/attachments/_attachment.dm b/code/game/objects/items/attachments/_attachment.dm new file mode 100644 index 000000000000..a6c25ec8cdf3 --- /dev/null +++ b/code/game/objects/items/attachments/_attachment.dm @@ -0,0 +1,99 @@ +///Most of the logic of attachments is held within the component which allows you to add other items as attachments in theory +/obj/item/attachment + name = "broken attachment" + desc = "alert coders" + icon = 'icons/obj/guns/attachments.dmi' + + //Slot the attachment goes on, also used in descriptions so should be player readable + var/slot = ATTACHMENT_SLOT_RAIL + ///various yes no flags associated with attachments. See defines for these: [_DEFINES/guns.dm] + var/attach_features_flags = ATTACH_REMOVABLE_HAND + ///See attachment component + var/list/valid_parents = list() + ///Unused.. but could hold extra callbacks I assume? + var/list/signals = list() + ///Component that handles most of the logic of attachments + var/datum/component/attachment/attachment_comp + + ///If the attachment is on or off + var/toggled = FALSE + var/toggle_on_sound = 'sound/items/flashlight_on.ogg' + var/toggle_off_sound = 'sound/items/flashlight_off.ogg' + + ///Determines the amount of pixels to move the icon state for the overlay. in the x direction + var/pixel_shift_x = 16 + ///Determines the amount of pixels to move the icon state for the overlay. in the y direction + var/pixel_shift_y = 16 + + //Toggle modifers are handled seperatly + ///Modifier applied to the parent + var/spread_mod = 0 + ///Modifier applied to the parent + var/spread_unwielded_mod = 0 + ///Modifier applied to the parent, deciseconds + var/wield_delay = 0 + ///Modifier applied to the parent + var/size_mod = 0 + +/obj/item/attachment/Initialize() + . = ..() + attachment_comp = AddComponent( \ + /datum/component/attachment, \ + slot, \ + attach_features_flags, \ + valid_parents, \ + CALLBACK(src, PROC_REF(apply_attachment)), \ + CALLBACK(src, PROC_REF(remove_attachment)), \ + CALLBACK(src, PROC_REF(toggle_attachment)), \ + CALLBACK(src, PROC_REF(on_preattack)), \ + signals) + +/obj/item/attachment/Destroy() + qdel(attachment_comp) + attachment_comp = null + . = ..() + +/obj/item/attachment/proc/toggle_attachment(obj/item/gun/gun, mob/user) + SHOULD_CALL_PARENT(TRUE) + + playsound(user, toggled ? toggle_on_sound : toggle_off_sound, 40, TRUE) + toggled = !toggled + icon_state = "[initial(icon_state)][toggled ? "-on" : ""]" + +/// Checks if a user should be allowed to attach this attachment to the given parent +/obj/item/attachment/proc/apply_attachment(obj/item/gun/gun, mob/user) + SHOULD_CALL_PARENT(TRUE) + + if(toggled) + to_chat(user, span_warning("You cannot attach [src] while it is active!")) + return FALSE + + apply_modifiers(gun, user, TRUE) + playsound(src.loc, 'sound/weapons/gun/pistol/mag_insert_alt.ogg', 75, 1) + return TRUE + +/obj/item/attachment/proc/remove_attachment(obj/item/gun/gun, mob/user) + SHOULD_CALL_PARENT(TRUE) + + if(toggled) + toggle_attachment(gun, user) + + apply_modifiers(gun, user, FALSE) + playsound(src.loc, 'sound/weapons/gun/pistol/mag_release_alt.ogg', 75, 1) + return TRUE + +/obj/item/attachment/proc/on_preattack(obj/item/gun/gun, atom/target, mob/user, list/params) + return FALSE + +///Handles the modifiers to the parent gun +/obj/item/attachment/proc/apply_modifiers(obj/item/gun/gun, mob/user, attaching) + if(attaching) + gun.spread += spread_mod + gun.spread_unwielded += spread_unwielded_mod + gun.wield_delay += wield_delay + gun.w_class += size_mod + else + gun.spread -= spread_mod + gun.spread_unwielded -= spread_unwielded_mod + gun.wield_delay -= wield_delay + gun.w_class -= size_mod diff --git a/code/game/objects/items/attachments/bayonet.dm b/code/game/objects/items/attachments/bayonet.dm new file mode 100644 index 000000000000..6b1961f4b693 --- /dev/null +++ b/code/game/objects/items/attachments/bayonet.dm @@ -0,0 +1,22 @@ +/obj/item/attachment/bayonet + name = "bayonet" + desc = "Stabby-Stabby" + icon_state = "bayonet" + force = 15 + throwforce = 10 + pickup_sound = 'sound/items/handling/knife1_pickup.ogg' + drop_sound = 'sound/items/handling/knife3_drop.ogg' + hitsound = 'sound/weapons/bladeslice.ogg' + attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + sharpness = IS_SHARP_ACCURATE + + pixel_shift_x = 1 + pixel_shift_y = 4 + spread_mod = 1 + wield_delay = 0.1 SECONDS + +/obj/item/attachment/bayonet/on_preattack(obj/item/gun/gun, atom/target, mob/living/user, list/params) + if(user.a_intent == INTENT_HARM && user.CanReach(target, src, TRUE)) + melee_attack_chain(user, target, params) + return COMPONENT_NO_ATTACK + diff --git a/code/game/objects/items/attachments/laser_sight.dm b/code/game/objects/items/attachments/laser_sight.dm new file mode 100644 index 000000000000..082da1153de5 --- /dev/null +++ b/code/game/objects/items/attachments/laser_sight.dm @@ -0,0 +1,23 @@ +/obj/item/attachment/laser_sight + name = "laser sight" + desc = "Designed to be rail-mounted on a compatible firearm to provide increased accuracy and decreased spread." + icon_state = "laserpointer" + + attach_features_flags = ATTACH_REMOVABLE_HAND|ATTACH_TOGGLE + pixel_shift_x = 1 + pixel_shift_y = 4 + wield_delay = 0.1 SECONDS + +/obj/item/attachment/laser_sight/toggle_attachment(obj/item/gun/gun, mob/user) + . = ..() + + if(toggled) + gun.spread -= 3 + gun.spread_unwielded -= 3 + gun.wield_delay -= 0.3 SECONDS + else + gun.spread += 3 + gun.spread_unwielded += 3 + gun.wield_delay += 0.3 SECONDS + + playsound(user, toggled ? 'sound/weapons/magin.ogg' : 'sound/weapons/magout.ogg', 40, TRUE) diff --git a/code/game/objects/items/attachments/rail_light.dm b/code/game/objects/items/attachments/rail_light.dm new file mode 100644 index 000000000000..0cfbe9661e9e --- /dev/null +++ b/code/game/objects/items/attachments/rail_light.dm @@ -0,0 +1,33 @@ +/obj/item/attachment/rail_light + name = "rail light" + desc = "A flashlight made to be mounted on a firearm." + icon_state = "raillight" + light_color = COLOR_LIGHT_ORANGE + light_system = MOVABLE_LIGHT_DIRECTIONAL + light_range = 4 + light_power = 0.8 + light_on = FALSE + + attach_features_flags = ATTACH_REMOVABLE_HAND|ATTACH_TOGGLE + pixel_shift_x = 1 + pixel_shift_y = 4 + wield_delay = 0.1 SECONDS + +/obj/item/attachment/rail_light/toggle_attachment(obj/item/gun/gun, mob/user) + . = ..() + set_light_on(toggled) + update_icon() + +/obj/item/attachment/rail_light/apply_attachment(obj/item/gun/gun, mob/user) + . = ..() + if(!.) + return + + set_light_flags(light_flags | LIGHT_ATTACHED) + +/obj/item/attachment/rail_light/remove_attachment(obj/item/gun/gun, mob/user) + . = ..() + if(!.) + return + + set_light_flags(light_flags & ~LIGHT_ATTACHED) diff --git a/code/game/objects/items/attachments/silencer.dm b/code/game/objects/items/attachments/silencer.dm new file mode 100644 index 000000000000..31cf3fc15b36 --- /dev/null +++ b/code/game/objects/items/attachments/silencer.dm @@ -0,0 +1,19 @@ +/obj/item/attachment/silencer + name = "suppressor" + desc = "An attachment for the barrel of a firearm. Muffles the gunshot and muzzle flash." + icon_state = "silencer" + + slot = ATTACHMENT_SLOT_MUZZLE + pixel_shift_x = 1 + pixel_shift_y = 2 + spread_mod = -1 + size_mod = 1 + +/obj/item/attachment/silencer/apply_attachment(obj/item/gun/gun, mob/user) + . = ..() + gun.suppressed = TRUE + +/obj/item/attachment/silencer/remove_attachment(obj/item/gun/gun, mob/user) + . = ..() + gun.suppressed = FALSE + return TRUE diff --git a/code/game/objects/items/attachments/stock.dm b/code/game/objects/items/attachments/stock.dm new file mode 100644 index 000000000000..1fe286c14296 --- /dev/null +++ b/code/game/objects/items/attachments/stock.dm @@ -0,0 +1,40 @@ +/obj/item/attachment/foldable_stock + name = "folding stock" + desc = "A folding stock that can be attached to certain weapons to improve stability and decreases recoil." + icon_state = "skm-carbine-stock" + slot = ATTACHMENT_SLOT_STOCK + attach_features_flags = ATTACH_TOGGLE + + pixel_shift_x = 17 + pixel_shift_y = 18 + + var/toggled_slowdown = 0.10 + var/toggled_wield_delay = -0.4 SECONDS + var/toggled_recoil_bonus = -2 + var/toggled_spread_bonus = -5 + +/obj/item/attachment/foldable_stock/toggle_attachment(obj/item/gun/gun, mob/user) + . = ..() + + if(toggled) + to_chat(user, span_notice("You unfold the stock on the [src].")) + gun.w_class += 1 + gun.wield_delay += toggled_wield_delay + gun.wield_slowdown += toggled_slowdown + gun.recoil += toggled_recoil_bonus + gun.spread += toggled_spread_bonus + else + to_chat(user, span_notice("You fold the stock on the [src].")) + gun.w_class -= 1 + gun.wield_delay -= toggled_wield_delay + gun.wield_slowdown -= toggled_slowdown + gun.recoil -= toggled_recoil_bonus + gun.spread -= toggled_spread_bonus + + if(gun.wielded) + user.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/gun, multiplicative_slowdown = gun.wield_slowdown) + + playsound(src, SOUND_EMPTY_MAG, 100, 1) + +/obj/item/attachment/foldable_stock/inteq + icon_state = "skm-inteqsmg-stock" diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm index 54dcfb36c131..47739ded1551 100644 --- a/code/game/objects/items/circuitboards/computer_circuitboards.dm +++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm @@ -362,7 +362,7 @@ build_path = /obj/machinery/computer/bounty /obj/item/circuitboard/computer/cargo - name = "Supply Console (Computer Board)" + name = "Outpost Comms Console (Computer Board)" icon_state = "supply" build_path = /obj/machinery/computer/cargo var/contraband = FALSE @@ -381,16 +381,6 @@ obj_flags |= EMAGGED to_chat(user, "You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband.") -/obj/item/circuitboard/computer/cargo/express - name = "Outpost Comms Console (Computer Board)" - build_path = /obj/machinery/computer/cargo/express - -/obj/item/circuitboard/computer/cargo/express/multitool_act(mob/living/user) - return - -/obj/item/circuitboard/computer/cargo/express/emag_act(mob/living/user) - return - /obj/item/circuitboard/computer/mining name = "Outpost Status Display (Computer Board)" icon_state = "supply" diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm index dca088c1be2e..204371ca0e51 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/devices/multitool.dm @@ -28,7 +28,7 @@ custom_materials = list(/datum/material/iron=50, /datum/material/glass=20) custom_premium_price = 450 toolspeed = 1 - usesound = 'sound/weapons/empty.ogg' + usesound = SOUND_EMPTY_MAG var/obj/machinery/buffer // simple machine buffer for device linkage var/mode = 0 diff --git a/code/game/objects/items/miscellaneous.dm b/code/game/objects/items/miscellaneous.dm index 0f5d79f13b37..619ebf3eb0e9 100644 --- a/code/game/objects/items/miscellaneous.dm +++ b/code/game/objects/items/miscellaneous.dm @@ -13,11 +13,10 @@ attack_verb = list("warned", "cautioned", "smashed") /obj/item/choice_beacon - name = "choice beacon" - desc = "Hey, why are you viewing this?!! Please let CentCom know about this odd occurrence." - icon = 'icons/obj/device.dmi' - icon_state = "gangtool-blue" - item_state = "radio" + name = "choice box" + desc = "A box containing items to choose." + icon = 'icons/obj/storage.dmi' + icon_state = "deliverypackage3" var/uses = 1 /obj/item/choice_beacon/attack_self(mob/user) @@ -31,41 +30,31 @@ if(user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return TRUE else - playsound(src, 'sound/machines/buzz-sigh.ogg', 40, TRUE) return FALSE /obj/item/choice_beacon/proc/generate_options(mob/living/M) var/list/display_names = generate_display_names() if(!display_names.len) return - var/choice = input(M,"Which item would you like to order?","Select an Item") as null|anything in sortList(display_names) + var/choice = input(M,"Which item would you like to pick?","Select an Item") as null|anything in sortList(display_names) if(!choice || !M.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return spawn_option(display_names[choice],M) uses-- if(!uses) + new /obj/effect/decal/cleanable/wrapping(get_turf(M)) qdel(src) else to_chat(M, "[uses] use[uses > 1 ? "s" : ""] remaining on the [src].") /obj/item/choice_beacon/proc/spawn_option(obj/choice,mob/living/M) - var/obj/new_item = new choice() - var/obj/structure/closet/supplypod/bluespacepod/pod = new() - pod.explosionSize = list(0,0,0,0) - new_item.forceMove(pod) - var/msg = "After making your selection, you notice a strange target on the ground. It might be best to step back!" - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(istype(H.ears, /obj/item/radio/headset)) - msg = "You hear something crackle in your ears for a moment before a voice speaks. \"Please stand by for a message from Central Command. Message as follows: Item request received. Your package is inbound, please stand back from the landing site. Message ends.\"" - to_chat(M, msg) - - new /obj/effect/pod_landingzone(get_turf(src), pod) + new choice(get_turf(M)) + playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, TRUE) /obj/item/choice_beacon/hero - name = "heroic beacon" - desc = "To summon heroes from the past to protect the future." + name = "heroic box" + desc = "To become heroes from the past to protect the future." /obj/item/choice_beacon/hero/generate_display_names() var/static/list/hero_item_list @@ -137,8 +126,8 @@ new /obj/item/grenade/chem_grenade/ghostbuster(src) /obj/item/choice_beacon/augments - name = "augment beacon" - desc = "Summons augmentations. Can be used 3 times!" + name = "augment box" + desc = "Contains augmentations. Can be used 3 times!" uses = 3 /obj/item/choice_beacon/augments/generate_display_names() @@ -157,10 +146,6 @@ augment_list[initial(A.name)] = A return augment_list -/obj/item/choice_beacon/augments/spawn_option(obj/choice,mob/living/M) - new choice(get_turf(M)) - to_chat(M, "You hear something crackle from the beacon for a moment before a voice speaks. \"Please stand by for a message from S.E.L.F. Message as follows: Item request received. Your package has been transported, use the autosurgeon supplied to apply the upgrade. Message ends.\"") - /obj/item/skub desc = "It's skub." name = "skub" @@ -217,8 +202,10 @@ #undef NICKNAME_CAP /obj/item/choice_beacon/ouija - name = "spirit board delivery beacon" + name = "spirit board box" desc = "Ghost communication on demand! It is unclear how this thing is still operational." + icon_state = "deliverybox" + w_class = WEIGHT_CLASS_BULKY /obj/item/choice_beacon/ouija/generate_display_names() var/static/list/ouija_spaghetti_list diff --git a/code/game/objects/items/pneumaticCannon.dm b/code/game/objects/items/pneumaticCannon.dm index 060e59f0f5de..5108a8713633 100644 --- a/code/game/objects/items/pneumaticCannon.dm +++ b/code/game/objects/items/pneumaticCannon.dm @@ -11,8 +11,8 @@ icon = 'icons/obj/pneumaticCannon.dmi' icon_state = "pneumaticCannon" item_state = "bulldog" - lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + lefthand_file = GUN_LEFTHAND_ICON + righthand_file = GUN_RIGHTHAND_ICON armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 60, "acid" = 50) var/maxWeightClass = 20 //The max weight of items that can fit into the cannon var/loadedWeightClass = 0 //The weight of items currently in the cannon diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index 5d87b42b78e5..92123969a4cd 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -624,7 +624,7 @@ new /obj/item/ammo_box/magazine/smgm45(src) new /obj/item/ammo_box/magazine/smgm45(src) new /obj/item/gun/ballistic/automatic/smg/c20r(src) - new /obj/item/suppressor/specialoffer(src) + new /obj/item/attachment/silencer(src) /obj/item/storage/backpack/duffelbag/syndie/bulldogbundle desc = "A large duffel bag containing a Bulldog, some drums, and a pair of thermal imaging glasses." diff --git a/code/game/objects/items/storage/briefcase.dm b/code/game/objects/items/storage/briefcase.dm index f55613dd4d21..64a3a11cf327 100644 --- a/code/game/objects/items/storage/briefcase.dm +++ b/code/game/objects/items/storage/briefcase.dm @@ -47,5 +47,5 @@ new /obj/item/clothing/under/syndicate/sniper(src) new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src) new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src) - new /obj/item/suppressor/specialoffer(src) + new /obj/item/attachment/silencer(src) diff --git a/code/game/objects/items/storage/guncases.dm b/code/game/objects/items/storage/guncases.dm index b70de7a01444..9cda5ac27a39 100644 --- a/code/game/objects/items/storage/guncases.dm +++ b/code/game/objects/items/storage/guncases.dm @@ -44,7 +44,7 @@ /obj/item/storage/guncase/beacon /obj/item/storage/guncase/beacon/PopulateContents() - new /obj/item/gun/ballistic/shotgun/doublebarrel/beacon(src) + new /obj/item/gun/ballistic/shotgun/doublebarrel/beacon/no_mag(src) /obj/item/storage/guncase/scout /obj/item/storage/guncase/scout/PopulateContents() @@ -79,7 +79,7 @@ /obj/item/storage/guncase/wt550 /obj/item/storage/guncase/wt550/PopulateContents() - new /obj/item/gun/ballistic/automatic/smg/wt550(src) + new /obj/item/gun/ballistic/automatic/smg/wt550/no_mag(src) new /obj/item/ammo_box/magazine/wt550m9/empty(src) new /obj/item/ammo_box/magazine/wt550m9/empty(src) diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm index bfbc4679af88..f34aae9e6f82 100644 --- a/code/game/objects/items/storage/uplink_kits.dm +++ b/code/game/objects/items/storage/uplink_kits.dm @@ -120,7 +120,7 @@ switch (pickweight(list( "bond" = 2, "ninja" = 1, "darklord" = 1, "white_whale_holy_grail" = 2, "mad_scientist" = 2, "bee" = 1, "mr_freeze" = 2, "made_man"= 1))) if("bond") new /obj/item/gun/ballistic/automatic/pistol/syndicate(src) - new /obj/item/suppressor(src) + new /obj/item/attachment/silencer(src) new /obj/item/ammo_box/magazine/m10mm(src) new /obj/item/ammo_box/magazine/m10mm(src) new /obj/item/clothing/under/chameleon(src) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index b1dfb479b66c..5ce082d79dc9 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -187,8 +187,8 @@ icon = 'icons/obj/guns/projectile.dmi' icon_state = "revolver" item_state = "gun" - lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + lefthand_file = GUN_LEFTHAND_ICON + righthand_file = GUN_RIGHTHAND_ICON flags_1 = CONDUCT_1 slot_flags = ITEM_SLOT_BELT w_class = WEIGHT_CLASS_NORMAL diff --git a/code/game/objects/structures/salvaging.dm b/code/game/objects/structures/salvaging.dm index ebefc58e5c01..d373f8eb94a9 100644 --- a/code/game/objects/structures/salvaging.dm +++ b/code/game/objects/structures/salvaging.dm @@ -673,7 +673,7 @@ /obj/effect/spawner/lootdrop/random_computer_circuit_rare loot = list( - /obj/item/circuitboard/computer/cargo/express = 5, + /obj/item/circuitboard/computer/cargo = 5, /obj/item/circuitboard/computer/communications = 5, /obj/item/circuitboard/computer/shuttle/helm = 5, /obj/item/circuitboard/computer/med_data = 5, diff --git a/code/modules/cargo/blackmarket/blackmarket_items/tools.dm b/code/modules/cargo/blackmarket/blackmarket_items/tools.dm index 384886ac30d3..d24cbf68171d 100644 --- a/code/modules/cargo/blackmarket/blackmarket_items/tools.dm +++ b/code/modules/cargo/blackmarket/blackmarket_items/tools.dm @@ -125,7 +125,7 @@ /datum/blackmarket_item/tool/suppressor name = "Suppressor" desc = "A suppressor, for when you to keep your murder on the down low." - item = /obj/item/suppressor + item = /obj/item/attachment/silencer price_min = 100 price_max = 700 diff --git a/code/modules/cargo/console.dm b/code/modules/cargo/console.dm index 143480b2bc71..82fd2c11d01a 100644 --- a/code/modules/cargo/console.dm +++ b/code/modules/cargo/console.dm @@ -1,42 +1,57 @@ +#define BEACON_COST 500 +#define SP_LINKED 1 +#define SP_READY 2 +#define SP_LAUNCH 3 +#define SP_UNLINK 4 +#define SP_UNREADY 5 + /obj/machinery/computer/cargo - name = "supply console" - desc = "Used to order supplies, approve requests, and control the shuttle." - icon_screen = "supply" + name = "outpost communications console" + desc = "This console allows the user to communicate with a nearby outpost to \ + purchase supplies and manage missions. Purchases are delivered near-instantly." + icon_screen = "supply_express" circuit = /obj/item/circuitboard/computer/cargo light_color = COLOR_BRIGHT_ORANGE - var/requestonly = FALSE var/contraband = FALSE var/self_paid = FALSE var/safety_warning = "For safety reasons, the automated supply shuttle \ cannot transport live organisms, human remains, classified nuclear weaponry, \ homing beacons or machinery housing any form of artificial intelligence." - var/blockade_warning = "Bluespace instability detected. Shuttle movement impossible." - /// radio used by the console to send messages on supply channel - var/obj/item/radio/headset/radio /// var that tracks message cooldown var/message_cooldown - -/obj/machinery/computer/cargo/request - name = "supply request console" - desc = "Used to request supplies from cargo." - icon_screen = "request" - circuit = /obj/item/circuitboard/computer/cargo/request - requestonly = TRUE + var/blockade_warning = "Bluespace instability detected. Delivery impossible." + var/message + /// Number of beacons printed. Used to determine beacon names. + var/printed_beacons = 0 + var/list/supply_pack_data + /// The currently linked supplypod beacon + var/obj/item/supplypod_beacon/beacon + /// Area instance that cargo pods are sent to + var/area/landingzone + /// The pod type used to deliver orders + var/podType = /obj/structure/closet/supplypod/centcompod + /// Cooldown to prevent printing supplypod beacon spam + var/cooldown = 0 + /// Is the console in beacon mode? exists to let beacon know when a pod may come in + var/use_beacon = FALSE + /// The account to charge purchases to, defaults to the cargo budget + var/datum/bank_account/charge_account /obj/machinery/computer/cargo/Initialize() . = ..() - radio = new /obj/item/radio/headset/headset_cargo(src) var/obj/item/circuitboard/computer/cargo/board = circuit contraband = board.contraband if (board.obj_flags & EMAGGED) obj_flags |= EMAGGED else obj_flags &= ~EMAGGED + generate_pack_data() /obj/machinery/computer/cargo/Destroy() - QDEL_NULL(radio) + if(beacon) + beacon.unlink_console() return ..() /obj/machinery/computer/cargo/proc/get_export_categories() @@ -65,49 +80,68 @@ /obj/machinery/computer/cargo/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, "Cargo", name) + ui = new(user, src, "OutpostCommunications", name) ui.open() + if(!charge_account) + reconnect() -/obj/machinery/computer/cargo/ui_data() +/obj/machinery/computer/cargo/ui_data(mob/user) + var/canBeacon = beacon && (isturf(beacon.loc) || ismob(beacon.loc))//is the beacon in a valid location? var/list/data = list() - data["location"] = SSshuttle.supply.getStatusText() - var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + + // not a big fan of get_containing_shuttle + var/obj/docking_port/mobile/D = SSshuttle.get_containing_shuttle(src) + var/datum/overmap/ship/controlled/ship + var/outpost_docked = FALSE if(D) - data["points"] = D.account_balance - data["away"] = SSshuttle.supply.get_docked() == SSshuttle.supply_away_port - data["self_paid"] = self_paid - data["docked"] = SSshuttle.supply.mode == SHUTTLE_IDLE - var/message = "Remember to stamp and send back the supply manifests." - if(SSshuttle.centcom_message) - message = SSshuttle.centcom_message + ship = D.current_ship + outpost_docked = istype(ship.docked_to, /datum/overmap/outpost) + + data["onShip"] = !isnull(ship) + data["numMissions"] = ship ? LAZYLEN(ship.missions) : 0 + data["maxMissions"] = ship ? ship.max_missions : 0 + data["outpostDocked"] = outpost_docked + data["points"] = charge_account ? charge_account.account_balance : 0 + data["siliconUser"] = user.has_unlimited_silicon_privilege && check_ship_ai_access(user) + data["beaconZone"] = beacon ? get_area(beacon) : ""//where is the beacon located? outputs in the tgui + data["usingBeacon"] = use_beacon //is the mode set to deliver to the beacon or the cargobay? + data["canBeacon"] = !use_beacon || canBeacon //is the mode set to beacon delivery, and is the beacon in a valid location? + data["canBuyBeacon"] = charge_account ? (cooldown <= 0 && charge_account.account_balance >= BEACON_COST) : FALSE + data["beaconError"] = use_beacon && !canBeacon ? "(BEACON ERROR)" : ""//changes button text to include an error alert if necessary + data["hasBeacon"] = beacon != null//is there a linked beacon? + data["beaconName"] = beacon ? beacon.name : "No Beacon Found" + data["printMsg"] = cooldown > 0 ? "Print Beacon for [BEACON_COST] credits ([cooldown])" : "Print Beacon for [BEACON_COST] credits"//buttontext for printing beacons + data["supplies"] = list() + message = "Sales are near-instantaneous - please choose carefully." if(SSshuttle.supplyBlocked) message = blockade_warning + if(use_beacon && !beacon) + message = "BEACON ERROR: BEACON MISSING"//beacon was destroyed + else if (use_beacon && !canBeacon) + message = "BEACON ERROR: MUST BE EXPOSED"//beacon's loc/user's loc must be a turf data["message"] = message - data["cart"] = list() - for(var/datum/supply_order/SO in SSshuttle.shoppinglist) - data["cart"] += list(list( - "object" = SO.pack.name, - "cost" = SO.pack.cost, - "id" = SO.id, - "orderer" = SO.orderer, - "paid" = !isnull(SO.paying_account) //paid by requester - )) + if(!supply_pack_data) + generate_pack_data() + stack_trace("You didn't give the cargo tech good advice, and he ripped the manifest. As a result, there was no pack data for [src]") + data["supplies"] = supply_pack_data + if (cooldown > 0)//cooldown used for printing beacons + cooldown-- - data["requests"] = list() - for(var/datum/supply_order/SO in SSshuttle.requestlist) - data["requests"] += list(list( - "object" = SO.pack.name, - "cost" = SO.pack.cost, - "orderer" = SO.orderer, - "reason" = SO.reason, - "id" = SO.id - )) + data["shipMissions"] = list() + data["outpostMissions"] = list() + + if(ship) + for(var/datum/mission/M as anything in ship.missions) + data["shipMissions"] += list(M.get_tgui_info()) + if(outpost_docked) + var/datum/overmap/outpost/out = ship.docked_to + for(var/datum/mission/M as anything in out.missions) + data["outpostMissions"] += list(M.get_tgui_info()) return data /obj/machinery/computer/cargo/ui_static_data(mob/user) var/list/data = list() - data["requestonly"] = requestonly data["supplies"] = list() for(var/pack in SSshuttle.supply_packs) var/datum/supply_pack/P = SSshuttle.supply_packs[pack] @@ -116,7 +150,7 @@ "name" = P.group, "packs" = list() ) - if((P.hidden && !(obj_flags & EMAGGED)) || (P.contraband && !contraband) || (P.special && !P.special_enabled) || P.DropPodOnly) + if(P.hidden && !(obj_flags & EMAGGED)) continue data["supplies"][P.group]["packs"] += list(list( "name" = P.name, @@ -124,7 +158,6 @@ "id" = pack, "desc" = P.desc || P.name, // If there is a description, use it. Otherwise use the pack's name. "small_item" = P.small_item, - "access" = P.access )) return data @@ -133,115 +166,154 @@ if(.) return switch(action) - if("send") - if(!SSshuttle.supply.canMove()) - say(safety_warning) + if("withdrawCash") + var/val = text2num(params["value"]) + // no giving yourself money + if(!charge_account || !val || val <= 0) return - if(SSshuttle.supplyBlocked) - say(blockade_warning) - return - if(SSshuttle.supply.get_docked() == SSshuttle.supply_home_port) - SSshuttle.supply.export_categories = get_export_categories() - SSshuttle.moveShuttle(SSshuttle.supply, SSshuttle.supply_away_port, TRUE) - say("The supply shuttle is departing.") - investigate_log("[key_name(usr)] sent the supply shuttle away.", INVESTIGATE_CARGO) - else - investigate_log("[key_name(usr)] called the supply shuttle.", INVESTIGATE_CARGO) - say("The supply shuttle has been called and will arrive in [SSshuttle.supply.timeLeft(600)] minutes.") - SSshuttle.moveShuttle(SSshuttle.supply, SSshuttle.supply_home_port, TRUE) - . = TRUE + if(charge_account.adjust_money(-val)) + var/obj/item/holochip/cash_chip = new /obj/item/holochip(drop_location(), val) + if(ishuman(usr)) + var/mob/living/carbon/human/user = usr + user.put_in_hands(cash_chip) + playsound(src, 'sound/machines/twobeep_high.ogg', 50, TRUE) + src.visible_message("[src] dispenses a holochip.") + return TRUE + + if("LZCargo") + use_beacon = FALSE + if (beacon) + beacon.update_status(SP_UNREADY) //ready light on beacon will turn off + if("LZBeacon") + use_beacon = TRUE + if (beacon) + beacon.update_status(SP_READY) //turns on the beacon's ready light + if("printBeacon") + if(charge_account?.adjust_money(-BEACON_COST)) + cooldown = 10//a ~ten second cooldown for printing beacons to prevent spam + var/obj/item/supplypod_beacon/C = new /obj/item/supplypod_beacon(drop_location()) + C.link_console(src, usr)//rather than in beacon's Initialize(), we can assign the computer to the beacon by reusing this proc) + printed_beacons++//printed_beacons starts at 0, so the first one out will be called beacon # 1 + beacon.name = "Supply Pod Beacon #[printed_beacons]" if("add") - if(istype(src, /obj/machinery/computer/cargo/express)) - return - var/id = text2path(params["id"]) - var/datum/supply_pack/pack = SSshuttle.supply_packs[id] - if(!istype(pack)) - return - if((pack.hidden && !(obj_flags & EMAGGED)) || (pack.contraband && !contraband) || pack.DropPodOnly) + var/area/ship/current_area = get_area(src) + var/datum/supply_pack/pack = SSshuttle.supply_packs[text2path(params["id"])] + if( \ + !pack || !charge_account?.has_money(pack.cost) || !istype(current_area) || \ + !istype(current_area.mobile_port.current_ship.docked_to, /datum/overmap/outpost) \ + ) return - var/name = "*None Provided*" - var/rank = "*None Provided*" - var/ckey = usr.ckey - if(ishuman(usr)) - var/mob/living/carbon/human/H = usr - name = H.get_authentification_name() - rank = H.get_assignment(hand_first = TRUE) - else if(issilicon(usr)) - name = usr.real_name - rank = "Silicon" - - var/datum/bank_account/account - if(self_paid && ishuman(usr)) - var/mob/living/carbon/human/H = usr - var/obj/item/card/id/id_card = H.get_idcard(TRUE) - if(!istype(id_card)) - say("No ID card detected.") - return - account = id_card.registered_account - if(!istype(account)) - say("Invalid bank account.") - return + var/turf/landing_turf + if(!isnull(beacon) && use_beacon) // prioritize beacons over landing in cargobay + landing_turf = get_turf(beacon) + beacon.update_status(SP_LAUNCH) + else if(!use_beacon)// find a suitable supplypod landing zone in cargobay + var/list/empty_turfs = list() + if(!landingzone) + reconnect() + if(!landingzone) + WARNING("[src] couldnt find a Ship/Cargo (aka cargobay) area on a ship, and as such it has set the supplypod landingzone to the area it resides in.") + landingzone = get_area(src) + for(var/turf/open/floor/T in landingzone.contents)//uses default landing zone + if(T.is_blocked_turf()) + continue + empty_turfs += T + CHECK_TICK + landing_turf = pick(empty_turfs) + + // note that, because of CHECK_TICK above, we aren't sure if we can + // afford the pack, even though we checked earlier. luckily adjust_money + // returns false if the account can't afford the price + if(landing_turf && charge_account.adjust_money(-pack.cost)) + var/name = "*None Provided*" + var/rank = "*None Provided*" + if(ishuman(usr)) + var/mob/living/carbon/human/H = usr + name = H.get_authentification_name() + rank = H.get_assignment(hand_first = TRUE) + else if(issilicon(usr)) + name = usr.real_name + rank = "Silicon" + var/datum/supply_order/SO = new(pack, name, rank, usr.ckey, "") + new /obj/effect/pod_landingzone(landing_turf, podType, SO) + update_appearance() // ?????????????????? + return TRUE - var/reason = "" - if(requestonly && !self_paid) - reason = stripped_input("Reason:", name, "") - if(isnull(reason) || ..()) + if("mission-act") + var/datum/mission/mission = locate(params["ref"]) + var/obj/docking_port/mobile/D = SSshuttle.get_containing_shuttle(src) + var/datum/overmap/ship/controlled/ship = D.current_ship + var/datum/overmap/outpost/outpost = ship.docked_to + if(!istype(outpost) || mission.source_outpost != outpost) // important to check these to prevent href fuckery + return + if(!mission.accepted) + if(LAZYLEN(ship.missions) >= ship.max_missions) return + mission.accept(ship, loc) + return TRUE + else if(mission.servant == ship) + if(mission.can_complete()) + mission.turn_in() + else + mission.give_up() + return TRUE - var/turf/T = get_turf(src) - var/datum/supply_order/SO = new(pack, name, rank, ckey, reason, account) - SO.generateRequisition(T) - if(requestonly && !self_paid) - SSshuttle.requestlist += SO - else - SSshuttle.shoppinglist += SO - if(self_paid) - say("Order processed. The price will be charged to [account.account_holder]'s bank account on delivery.") - if(requestonly && message_cooldown < world.time) - radio.talk_into(src, "A new order has been requested.", RADIO_CHANNEL_COMMAND) - message_cooldown = world.time + 30 SECONDS - . = TRUE - if("remove") - var/id = text2num(params["id"]) - for(var/datum/supply_order/SO in SSshuttle.shoppinglist) - if(SO.id == id) - SSshuttle.shoppinglist -= SO - . = TRUE - break - if("clear") - SSshuttle.shoppinglist.Cut() - . = TRUE - if("approve") - var/id = text2num(params["id"]) - for(var/datum/supply_order/SO in SSshuttle.requestlist) - if(SO.id == id) - SSshuttle.requestlist -= SO - SSshuttle.shoppinglist += SO - . = TRUE - break - if("deny") - var/id = text2num(params["id"]) - for(var/datum/supply_order/SO in SSshuttle.requestlist) - if(SO.id == id) - SSshuttle.requestlist -= SO - . = TRUE - break - if("denyall") - SSshuttle.requestlist.Cut() - . = TRUE - if("toggleprivate") - self_paid = !self_paid - . = TRUE - if(.) - post_signal("supply") +/obj/machinery/computer/cargo/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock) + . = ..() + reconnect(port) -/obj/machinery/computer/cargo/proc/post_signal(command) +/obj/machinery/computer/cargo/proc/reconnect(obj/docking_port/mobile/port) + if(!port) + var/area/ship/current_area = get_area(src) + if(!istype(current_area)) + return + port = current_area.mobile_port + if(!port) + return + charge_account = port.current_ship.ship_account + landingzone = locate(/area/ship/cargo) in port.shuttle_areas - var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS) +/obj/machinery/computer/cargo/attackby(obj/item/W, mob/living/user, params) + var/value = W.get_item_credit_value() + if(value && charge_account) + charge_account.adjust_money(value) + to_chat(user, "You deposit [W]. The Vessel Budget is now [charge_account.account_balance] cr.") + qdel(W) + return TRUE + else if(istype(W, /obj/item/supplypod_beacon)) + var/obj/item/supplypod_beacon/sb = W + if (sb.cargo_console != src) + sb.link_console(src, user) + return TRUE + else + to_chat(user, "[src] is already linked to [sb].") + ..() - if(!frequency) - return +/obj/machinery/computer/cargo/proc/generate_pack_data() + supply_pack_data = list() + for(var/pack in SSshuttle.supply_packs) + var/datum/supply_pack/P = SSshuttle.supply_packs[pack] + if(!supply_pack_data[P.group]) + supply_pack_data[P.group] = list( + "name" = P.group, + "packs" = list() + ) + if((P.hidden)) + continue + supply_pack_data[P.group]["packs"] += list(list( + "name" = P.name, + "cost" = P.cost, + "id" = pack, + "desc" = P.desc || P.name // If there is a description, use it. Otherwise use the pack's name. + )) + +/obj/machinery/computer/cargo/retro + icon = 'icons/obj/machines/retro_computer.dmi' + icon_state = "computer-retro" + deconpath = /obj/structure/frame/computer/retro - var/datum/signal/status_signal = new(list("command" = command)) - frequency.post_signal(src, status_signal) +/obj/machinery/computer/cargo/solgov + icon = 'icons/obj/machines/retro_computer.dmi' + icon_state = "computer-solgov" + deconpath = /obj/structure/frame/computer/solgov diff --git a/code/modules/cargo/expressconsole.dm b/code/modules/cargo/expressconsole.dm deleted file mode 100644 index 81409d63d031..000000000000 --- a/code/modules/cargo/expressconsole.dm +++ /dev/null @@ -1,262 +0,0 @@ -#define BEACON_COST 500 -#define SP_LINKED 1 -#define SP_READY 2 -#define SP_LAUNCH 3 -#define SP_UNLINK 4 -#define SP_UNREADY 5 - -/obj/machinery/computer/cargo/express - name = "outpost communications console" - desc = "This console allows the user to communicate with a nearby outpost to \ - purchase supplies and manage missions. Purchases are delivered near-instantly." - icon_screen = "supply_express" - circuit = /obj/item/circuitboard/computer/cargo/express - var/blockade_warning = "Bluespace instability detected. Delivery impossible." - - var/message - /// Number of beacons printed. Used to determine beacon names. - var/printed_beacons = 0 - var/list/meme_pack_data - /// The currently linked supplypod beacon - var/obj/item/supplypod_beacon/beacon - /// Area instance that cargo pods are sent to - var/area/landingzone - /// The pod type used to deliver orders - var/podType = /obj/structure/closet/supplypod/centcompod - /// Cooldown to prevent printing supplypod beacon spam - var/cooldown = 0 - /// Is the console in beacon mode? exists to let beacon know when a pod may come in - var/use_beacon = FALSE - /// The account to charge purchases to, defaults to the cargo budget - var/datum/bank_account/charge_account - -/obj/machinery/computer/cargo/express/retro - icon = 'icons/obj/machines/retro_computer.dmi' - icon_state = "computer-retro" - deconpath = /obj/structure/frame/computer/retro - -/obj/machinery/computer/cargo/express/solgov - icon = 'icons/obj/machines/retro_computer.dmi' - icon_state = "computer-solgov" - deconpath = /obj/structure/frame/computer/solgov - -/obj/machinery/computer/cargo/express/Initialize() - . = ..() - packin_up() - -/obj/machinery/computer/cargo/express/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock) - . = ..() - reconnect(port) - -/obj/machinery/computer/cargo/express/proc/reconnect(obj/docking_port/mobile/port) - if(!port) - var/area/ship/current_area = get_area(src) - if(!istype(current_area)) - return - port = current_area.mobile_port - if(!port) - return - charge_account = port.current_ship.ship_account - landingzone = locate(/area/ship/cargo) in port.shuttle_areas - -/obj/machinery/computer/cargo/express/Destroy() - if(beacon) - beacon.unlink_console() - return ..() - -/obj/machinery/computer/cargo/express/attackby(obj/item/W, mob/living/user, params) - var/value = W.get_item_credit_value() - if(value && charge_account) - charge_account.adjust_money(value) - to_chat(user, "You deposit [W]. The Vessel Budget is now [charge_account.account_balance] cr.") - qdel(W) - return TRUE - else if(istype(W, /obj/item/supplypod_beacon)) - var/obj/item/supplypod_beacon/sb = W - if (sb.express_console != src) - sb.link_console(src, user) - return TRUE - else - to_chat(user, "[src] is already linked to [sb].") - ..() - -/obj/machinery/computer/cargo/express/proc/packin_up() // oh shit, I'm sorry - meme_pack_data = list() // sorry for what? - for(var/pack in SSshuttle.supply_packs) // our quartermaster taught us not to be ashamed of our supply packs - var/datum/supply_pack/P = SSshuttle.supply_packs[pack] // specially since they're such a good price and all - if(!meme_pack_data[P.group]) // yeah, I see that, your quartermaster gave you good advice - meme_pack_data[P.group] = list( // it gets cheaper when I return it - "name" = P.group, // mmhm - "packs" = list() // sometimes, I return it so much, I rip the manifest - ) // see, my quartermaster taught me a few things too - if((P.hidden)) // like, how not to rip the manifest - continue// by using someone else's crate - meme_pack_data[P.group]["packs"] += list(list( - "name" = P.name, - "cost" = P.cost, - "id" = pack, - "desc" = P.desc || P.name // If there is a description, use it. Otherwise use the pack's name. - )) - -/obj/machinery/computer/cargo/express/ui_interact(mob/living/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "OutpostCommunications", name) - ui.open() - if(!charge_account) - reconnect() - -/obj/machinery/computer/cargo/express/ui_data(mob/user) - var/canBeacon = beacon && (isturf(beacon.loc) || ismob(beacon.loc))//is the beacon in a valid location? - var/list/data = list() - - // not a big fan of get_containing_shuttle - var/obj/docking_port/mobile/D = SSshuttle.get_containing_shuttle(src) - var/datum/overmap/ship/controlled/ship - var/outpost_docked = FALSE - if(D) - ship = D.current_ship - outpost_docked = istype(ship.docked_to, /datum/overmap/outpost) - - data["onShip"] = !isnull(ship) - data["numMissions"] = ship ? LAZYLEN(ship.missions) : 0 - data["maxMissions"] = ship ? ship.max_missions : 0 - data["outpostDocked"] = outpost_docked - data["points"] = charge_account ? charge_account.account_balance : 0 - data["siliconUser"] = user.has_unlimited_silicon_privilege && check_ship_ai_access(user) - data["beaconZone"] = beacon ? get_area(beacon) : ""//where is the beacon located? outputs in the tgui - data["usingBeacon"] = use_beacon //is the mode set to deliver to the beacon or the cargobay? - data["canBeacon"] = !use_beacon || canBeacon //is the mode set to beacon delivery, and is the beacon in a valid location? - data["canBuyBeacon"] = charge_account ? (cooldown <= 0 && charge_account.account_balance >= BEACON_COST) : FALSE - data["beaconError"] = use_beacon && !canBeacon ? "(BEACON ERROR)" : ""//changes button text to include an error alert if necessary - data["hasBeacon"] = beacon != null//is there a linked beacon? - data["beaconName"] = beacon ? beacon.name : "No Beacon Found" - data["printMsg"] = cooldown > 0 ? "Print Beacon for [BEACON_COST] credits ([cooldown])" : "Print Beacon for [BEACON_COST] credits"//buttontext for printing beacons - data["supplies"] = list() - message = "Sales are near-instantaneous - please choose carefully." - if(SSshuttle.supplyBlocked) - message = blockade_warning - if(use_beacon && !beacon) - message = "BEACON ERROR: BEACON MISSING"//beacon was destroyed - else if (use_beacon && !canBeacon) - message = "BEACON ERROR: MUST BE EXPOSED"//beacon's loc/user's loc must be a turf - data["message"] = message - if(!meme_pack_data) - packin_up() - stack_trace("You didn't give the cargo tech good advice, and he ripped the manifest. As a result, there was no pack data for [src]") - data["supplies"] = meme_pack_data - if (cooldown > 0)//cooldown used for printing beacons - cooldown-- - - data["shipMissions"] = list() - data["outpostMissions"] = list() - - if(ship) - for(var/datum/mission/M as anything in ship.missions) - data["shipMissions"] += list(M.get_tgui_info()) - if(outpost_docked) - var/datum/overmap/outpost/out = ship.docked_to - for(var/datum/mission/M as anything in out.missions) - data["outpostMissions"] += list(M.get_tgui_info()) - - return data - -/obj/machinery/computer/cargo/express/ui_act(action, params, datum/tgui/ui) - . = ..() - if(.) - return - - switch(action) - if("withdrawCash") - var/val = text2num(params["value"]) - // no giving yourself money - if(!charge_account || !val || val <= 0) - return - if(charge_account.adjust_money(-val)) - var/obj/item/holochip/cash_chip = new /obj/item/holochip(drop_location(), val) - if(ishuman(usr)) - var/mob/living/carbon/human/user = usr - user.put_in_hands(cash_chip) - playsound(src, 'sound/machines/twobeep_high.ogg', 50, TRUE) - src.visible_message("[src] dispenses a holochip.") - return TRUE - - if("LZCargo") - use_beacon = FALSE - if (beacon) - beacon.update_status(SP_UNREADY) //ready light on beacon will turn off - if("LZBeacon") - use_beacon = TRUE - if (beacon) - beacon.update_status(SP_READY) //turns on the beacon's ready light - if("printBeacon") - if(charge_account?.adjust_money(-BEACON_COST)) - cooldown = 10//a ~ten second cooldown for printing beacons to prevent spam - var/obj/item/supplypod_beacon/C = new /obj/item/supplypod_beacon(drop_location()) - C.link_console(src, usr)//rather than in beacon's Initialize(), we can assign the computer to the beacon by reusing this proc) - printed_beacons++//printed_beacons starts at 0, so the first one out will be called beacon # 1 - beacon.name = "Supply Pod Beacon #[printed_beacons]" - - if("add") - var/area/ship/current_area = get_area(src) - var/datum/supply_pack/pack = SSshuttle.supply_packs[text2path(params["id"])] - if( \ - !pack || !charge_account?.has_money(pack.cost) || !istype(current_area) || \ - !istype(current_area.mobile_port.current_ship.docked_to, /datum/overmap/outpost) \ - ) - return - - var/turf/landing_turf - if(!isnull(beacon) && use_beacon) // prioritize beacons over landing in cargobay - landing_turf = get_turf(beacon) - beacon.update_status(SP_LAUNCH) - else if(!use_beacon)// find a suitable supplypod landing zone in cargobay - var/list/empty_turfs = list() - if(!landingzone) - reconnect() - if(!landingzone) - WARNING("[src] couldnt find a Ship/Cargo (aka cargobay) area on a ship, and as such it has set the supplypod landingzone to the area it resides in.") - landingzone = get_area(src) - for(var/turf/open/floor/T in landingzone.contents)//uses default landing zone - if(T.is_blocked_turf()) - continue - empty_turfs += T - CHECK_TICK - landing_turf = pick(empty_turfs) - - // note that, because of CHECK_TICK above, we aren't sure if we can - // afford the pack, even though we checked earlier. luckily adjust_money - // returns false if the account can't afford the price - if(landing_turf && charge_account.adjust_money(-pack.cost)) - var/name = "*None Provided*" - var/rank = "*None Provided*" - if(ishuman(usr)) - var/mob/living/carbon/human/H = usr - name = H.get_authentification_name() - rank = H.get_assignment(hand_first = TRUE) - else if(issilicon(usr)) - name = usr.real_name - rank = "Silicon" - var/datum/supply_order/SO = new(pack, name, rank, usr.ckey, "") - new /obj/effect/pod_landingzone(landing_turf, podType, SO) - update_appearance() // ?????????????????? - return TRUE - - if("mission-act") - var/datum/mission/mission = locate(params["ref"]) - var/obj/docking_port/mobile/D = SSshuttle.get_containing_shuttle(src) - var/datum/overmap/ship/controlled/ship = D.current_ship - var/datum/overmap/outpost/outpost = ship.docked_to - if(!istype(outpost) || mission.source_outpost != outpost) // important to check these to prevent href fuckery - return - if(!mission.accepted) - if(LAZYLEN(ship.missions) >= ship.max_missions) - return - mission.accept(ship, loc) - return TRUE - else if(mission.servant == ship) - if(mission.can_complete()) - mission.turn_in() - else - mission.give_up() - return TRUE diff --git a/code/modules/cargo/packs/gun.dm b/code/modules/cargo/packs/gun.dm index 132e62bb0ada..4aaf2f60bef8 100644 --- a/code/modules/cargo/packs/gun.dm +++ b/code/modules/cargo/packs/gun.dm @@ -23,19 +23,19 @@ /datum/supply_pack/gun/commanders name = "Commander Pistol Crate" desc = "Contains a modified Candor 'Commander' pistol, produced by Nanotrasen and chambered in 9mm." - cost = 750 + cost = 1000 contains = list(/obj/item/storage/pistolcase/commander) /datum/supply_pack/gun/makarovs name = "Stechkin Pistol Crate" desc = "Contains a concealable stechkin pistol, produced by Scarborough Arms and chambered in 10mm." - cost = 1000 + cost = 1250 contains = list(/obj/item/storage/pistolcase/stechkin) /datum/supply_pack/gun/candors name = "Candor Pistol Crate" desc = "Contains a Candor pistol, the trusty sidearm of any spacer, produced by Hunter's Pride and chambered in .45 ACP." - cost = 1000 + cost = 1250 contains = list(/obj/item/storage/pistolcase/candor) /datum/supply_pack/gun/pepperbox @@ -120,14 +120,14 @@ name = "Hellfire Shotgun Crate" desc = "For when you need to deal with 8 hooligans. Contains a pump shotgun, with a 8-round capacity." cost = 2000 - contains = list(/obj/item/gun/ballistic/shotgun/hellfire) + contains = list(/obj/item/storage/guncase/hellfire) crate_name = "shotgun crate" /datum/supply_pack/gun/brimstone_shotgun name = "Brimstone Shotgun Crate" desc = "For when you need to deal with 5 hooligans, and QUICKLY. Contains a slamfire shotgun, with a 5-round capacity. Warranty voided if sawed off." cost = 2000 - contains = list(/obj/item/gun/ballistic/shotgun/brimstone) + contains = list(/obj/item/storage/guncase/brimstone) crate_name = "shotgun crate" /* @@ -159,33 +159,61 @@ name = "Scout Sniper Rifle Crate" desc = "Contains a traditional scoped rifle to hunt wildlife and big game from a respectful distance. Chambered in powerful .300 Magnum." cost = 5500 - contains = list(/obj/item/gun/ballistic/rifle/scout) + contains = list(/obj/item/storage/guncase/scout) crate_name = "rifle crate" /datum/supply_pack/gun/cobra20 name = "Cobra-20 SMG Crate" desc = "Contains a .45 submachine gun, manufactured by Scaraborough Arms and chambered in .45" - cost = 3000 + cost = 6000 contains = list(/obj/item/storage/guncase/cobra) crate_name = "SMG crate" /datum/supply_pack/gun/wt550 name = "WT-550 Auto Rifle Crate" desc = "Contains a high-powered, automatic personal defense weapon chambered in 4.6x30mm." - cost = 4000 + cost = 6000 contains = list(/obj/item/storage/guncase/wt550) crate_name = "auto rifle crate" /datum/supply_pack/gun/p16 name = "P16 Assault Rifle Crate" desc = "Contains a high-powered, automatic rifle chambered in 5.56mm." - cost = 5000 + cost = 9000 contains = list(/obj/item/storage/guncase/p16) crate_name = "auto rifle crate" /datum/supply_pack/gun/skm name = "SKM-24 Rifle Crate" desc = "Contains a high-powered, automatic rifle chambered in 7.62x40mm CLIP." - cost = 5000 + cost = 9000 contains = list(/obj/item/storage/guncase/skm) crate_name = "auto rifle crate" + +/datum/supply_pack/gun/attachment/rail_light + name = "Tactical Rail Light Crate" + desc = "Contains a single rail light to be mounted on a firearm." + cost = 250 + contains = list(/obj/item/attachment/rail_light) + crate_name = "rail light crate" + +/datum/supply_pack/gun/attachment/laser_sight + name = "Laser Sight Crate" + desc = "Contains a single rail light to be mounted on a firearm." + cost = 250 + contains = list(/obj/item/attachment/laser_sight) + crate_name = "laser sight crate" + +/datum/supply_pack/gun/attachment/bayonet + name = "Bayonet Crate" + desc = "Contains a single bayonet to be mounted on a firearm." + cost = 250 + contains = list(/obj/item/attachment/bayonet) + crate_name = "bayonet crate" + +/datum/supply_pack/gun/attachment/silencer + name = "Suppressor Crate" + desc = "Contains a single suppressor to be mounted on a firearm." + cost = 250 + contains = list(/obj/item/attachment/silencer) + crate_name = "silencer crate" diff --git a/code/modules/cargo/supplypod_beacon.dm b/code/modules/cargo/supplypod_beacon.dm index 11fd10229e5e..b9c41a29e11f 100644 --- a/code/modules/cargo/supplypod_beacon.dm +++ b/code/modules/cargo/supplypod_beacon.dm @@ -7,7 +7,7 @@ lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' w_class = WEIGHT_CLASS_SMALL - var/obj/machinery/computer/cargo/express/express_console + var/obj/machinery/computer/cargo/cargo_console var/linked = FALSE var/ready = FALSE var/launched = FALSE @@ -49,39 +49,39 @@ /obj/item/supplypod_beacon/examine(user) . = ..() - if(!express_console) + if(!cargo_console) . += "[src] is not currently linked to an Express Supply console." else . += "Alt-click to unlink it from the Express Supply console." /obj/item/supplypod_beacon/Destroy() - if(express_console) - express_console.beacon = null + if(cargo_console) + cargo_console.beacon = null return ..() /obj/item/supplypod_beacon/proc/unlink_console() - if(express_console) - express_console.beacon = null - express_console = null + if(cargo_console) + cargo_console.beacon = null + cargo_console = null update_status(SP_UNLINK) update_status(SP_UNREADY) -/obj/item/supplypod_beacon/proc/link_console(obj/machinery/computer/cargo/express/C, mob/living/user) +/obj/item/supplypod_beacon/proc/link_console(obj/machinery/computer/cargo/C, mob/living/user) if (C.beacon)//if new console has a beacon, then... C.beacon.unlink_console()//unlink the old beacon from new console - if (express_console)//if this beacon has an express console - express_console.beacon = null//remove the connection the expressconsole has from beacons - express_console = C//set the linked console var to the console - express_console.beacon = src//out with the old in with the news + if (cargo_console)//if this beacon has an express console + cargo_console.beacon = null//remove the connection the expressconsole has from beacons + cargo_console = C//set the linked console var to the console + cargo_console.beacon = src//out with the old in with the news update_status(SP_LINKED) - if (express_console.use_beacon) + if (cargo_console.use_beacon) update_status(SP_READY) to_chat(user, "[src] linked to [C].") /obj/item/supplypod_beacon/AltClick(mob/user) if (!user.canUseTopic(src, !issilicon(user))) return - if (express_console) + if (cargo_console) unlink_console() else to_chat(user, "There is no linked console.") diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 0fd922a2856a..87a33b0c989b 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -107,6 +107,9 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( cmd_admin_pm(href_list["priv_msg"],null) return + if(href_list["commandbar_typing"]) + handle_commandbar_typing(href_list) + switch(href_list["_src_"]) if("holder") hsrc = holder @@ -226,6 +229,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( // Instantiate tgui panel tgui_panel = new(src, "browseroutput") + initialize_commandbar_spy() + GLOB.ahelp_tickets.client_login(src) GLOB.interviews.client_login(src) GLOB.requests.client_login(src) diff --git a/code/modules/client/loadout/loadout_accessories.dm b/code/modules/client/loadout/loadout_accessories.dm index 70225b60cc2e..c1e4d7a088a8 100644 --- a/code/modules/client/loadout/loadout_accessories.dm +++ b/code/modules/client/loadout/loadout_accessories.dm @@ -72,11 +72,6 @@ path = /obj/item/clothing/neck/stethoscope allowed_roles = list("Medical Doctor", "Chief Medical Officer") -/datum/gear/accessory/collar - display_name = "pet collar" - description = "Only the truly insane would wear this around their neck." - path = /obj/item/clothing/neck/petcollar - /datum/gear/accessory/gloves/black display_name = "black gloves" description = "Standard hand coverings for everyday use." @@ -97,14 +92,3 @@ description = "Excessively fancy elbow-length gloves." path = /obj/item/clothing/gloves/color/evening slot = ITEM_SLOT_GLOVES - -/datum/gear/accessory/tiki - display_name = "tiki mask" - description = "A wooden mask, simple, really." - path = /obj/item/clothing/mask/gas/tiki_mask - slot = ITEM_SLOT_MASK - -/datum/gear/accessory/joymask - display_name = "face with tears of joy mask" - path = /obj/item/clothing/mask/joy - slot = ITEM_SLOT_MASK diff --git a/code/modules/client/loadout/loadout_general.dm b/code/modules/client/loadout/loadout_general.dm index 6277a8a3a601..8bb3ff3cb69d 100644 --- a/code/modules/client/loadout/loadout_general.dm +++ b/code/modules/client/loadout/loadout_general.dm @@ -160,14 +160,6 @@ display_name = "tool, emergency crowbar" path = /obj/item/crowbar/red -/datum/gear/balloon - display_name = "toy, balloon" - path = /obj/item/toy/balloon - -/datum/gear/balloon/ian - display_name = "toy, ian balloon" - path = /obj/item/toy/balloon/corgi - /datum/gear/surgical_mask display_name = "surgical mask" path = /obj/item/clothing/mask/surgical diff --git a/code/modules/client/loadout/loadout_hat.dm b/code/modules/client/loadout/loadout_hat.dm index 3d2905720f0a..23e34d7d19c3 100644 --- a/code/modules/client/loadout/loadout_hat.dm +++ b/code/modules/client/loadout/loadout_hat.dm @@ -92,10 +92,6 @@ display_name = "beanie" path = /obj/item/clothing/head/beanie -/datum/gear/hat/tinfoil - display_name = "tinfoil hat" - path = /obj/item/clothing/head/foilhat - /datum/gear/hat/wig display_name = "wig" path = /obj/item/clothing/head/wig @@ -104,20 +100,6 @@ display_name = "cowboy hat" path = /obj/item/clothing/head/cowboy -/datum/gear/hat/catears - display_name = "cat ears" - path = /obj/item/clothing/head/kitty - -/datum/gear/hat/horse - display_name = "horse mask" - path = /obj/item/clothing/mask/horsehead - slot = ITEM_SLOT_MASK - -/datum/gear/hat/piratehat - display_name = "pirate hat" - description = "Yarr. Comes with one free pirate speak manual." - path = /obj/item/clothing/head/pirate - /datum/gear/hat/trapper display_name = "trapper hat" path = /obj/item/clothing/head/trapper diff --git a/code/modules/client/loadout/loadout_suit.dm b/code/modules/client/loadout/loadout_suit.dm index dbed1feb8ee8..f8757bfa5b38 100644 --- a/code/modules/client/loadout/loadout_suit.dm +++ b/code/modules/client/loadout/loadout_suit.dm @@ -107,7 +107,7 @@ path = /obj/item/clothing/suit/toggle/labcoat /datum/gear/suit/raincoat - display_name = "Cybersun labcoat" + display_name = "translucent labcoat" description = "Designer lab safety equipment. You're pretty sure this is just a raincoat." path = /obj/item/clothing/suit/toggle/labcoat/raincoat diff --git a/code/modules/client/loadout/loadout_uniform.dm b/code/modules/client/loadout/loadout_uniform.dm index 616c4308b437..96b4088b65bd 100644 --- a/code/modules/client/loadout/loadout_uniform.dm +++ b/code/modules/client/loadout/loadout_uniform.dm @@ -160,10 +160,6 @@ display_name = "suit, charcoal" path = /obj/item/clothing/under/suit/charcoal -/datum/gear/uniform/suit/galaxy - display_name = "suit, galaxy" - path = /obj/item/clothing/under/rank/civilian/lawyer/galaxy - /datum/gear/uniform/suit/white_skirt display_name = "suitskirt, white shirt" path = /obj/item/clothing/under/suit/black/skirt @@ -236,8 +232,3 @@ /datum/gear/uniform/dress/rilena display_name = "red dress, Ri cosplay" path = /obj/item/clothing/under/dress/rilena - -//Premium -/datum/gear/uniform/tacticool - display_name = "tacticool turtleneck" - path = /obj/item/clothing/under/syndicate/tacticool diff --git a/code/modules/client/verbs/typing.dm b/code/modules/client/verbs/typing.dm new file mode 100644 index 000000000000..28abf10ee7e8 --- /dev/null +++ b/code/modules/client/verbs/typing.dm @@ -0,0 +1,28 @@ +#define IC_VERBS list("say", "me", "whisper") + +/client/var/commandbar_thinking = FALSE +/client/var/commandbar_typing = FALSE + +/client/proc/initialize_commandbar_spy() + src << output('html/typing_indicator.html', "commandbar_spy") + +/client/proc/handle_commandbar_typing(href_list) + if (length(href_list["verb"]) < 1 || !(lowertext(href_list["verb"]) in IC_VERBS) || text2num(href_list["argument_length"]) < 1) + if (commandbar_typing) + commandbar_typing = FALSE + stop_typing() + return + + if (!commandbar_typing) + commandbar_typing = TRUE + start_typing() + +/client/proc/start_typing() + mob.set_typing_indicator(TRUE) + +/client/proc/stop_typing() + if(isnull(mob)) + return FALSE + mob.set_typing_indicator(FALSE) + +#undef IC_VERBS diff --git a/code/modules/clothing/suits/labcoat.dm b/code/modules/clothing/suits/labcoat.dm index 858b494564e6..798a34606bc1 100644 --- a/code/modules/clothing/suits/labcoat.dm +++ b/code/modules/clothing/suits/labcoat.dm @@ -59,11 +59,11 @@ armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 10, rad = 0, fire = 50, acid = 50) /obj/item/clothing/suit/toggle/labcoat/raincoat - name = "\improper Cybersun labcoat" - desc = {"A translucent, uniquely designed labcoat from Cybersun Solutions. It's made from a special material that actively repels fluids. + name = "translucent labcoat" + desc = {"A uniquely designed, translucent labcoat. It's made from a special material that actively repels fluids. You're pretty sure this is just a raincoat. -Wearing a raincoat inside is like wearing sunglasses at night. A good Cybersun exec does both. +Wearing a raincoat inside is like wearing sunglasses at night. A good chemist does both. "} icon_state = "raincoat" item_state = "raincoat" diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index ced086e1dfc6..4774ea852424 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -476,15 +476,15 @@ GLOBAL_LIST_INIT(hallucination_list, list( A = image(image_file,H,"dualsaberred1", layer=ABOVE_MOB_LAYER) if("taser") if(side == "right") - image_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + image_file = GUN_RIGHTHAND_ICON else - image_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' + image_file = GUN_LEFTHAND_ICON A = image(image_file,H,"advtaserstun4", layer=ABOVE_MOB_LAYER) if("ebow") if(side == "right") - image_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + image_file = GUN_RIGHTHAND_ICON else - image_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' + image_file = GUN_LEFTHAND_ICON A = image(image_file,H,"crossbow", layer=ABOVE_MOB_LAYER) if("baton") if(side == "right") diff --git a/code/modules/instruments/items.dm b/code/modules/instruments/items.dm index 022b3278e92b..490742d7cdf7 100644 --- a/code/modules/instruments/items.dm +++ b/code/modules/instruments/items.dm @@ -271,9 +271,8 @@ hitsound = 'sound/items/bikehorn.ogg' /obj/item/choice_beacon/music - name = "instrument delivery beacon" - desc = "Summon your tool of art." - icon_state = "gangtool-red" + name = "instrument box" + desc = "Contains your tool of art." /obj/item/choice_beacon/music/generate_display_names() var/static/list/instruments @@ -299,9 +298,8 @@ return instruments /obj/item/choice_beacon/rnd - name = "C.R.E.W.M.A.T.E type R&D Choice Beacon" - desc = "This aging launch beacon summons a limited production RND package from a nearby orbital satellite, delivered via impact pod." - icon_state = "gangtool-sus" + name = "C.R.E.W.M.A.T.E type R&D box" + desc = "This box contains a limited production RND package." /obj/item/choice_beacon/rnd/generate_display_names() var/static/list/rndboxes diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index 030e592d80cd..b6073d4c86a2 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -113,7 +113,7 @@ /obj/item/kinetic_crusher/ui_action_click(mob/user, actiontype) set_light_on(!light_on) - playsound(user, 'sound/weapons/empty.ogg', 100, TRUE) + playsound(user, SOUND_EMPTY_MAG, 100, TRUE) update_appearance() diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index d4aba67937d1..a2b48d9319b9 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -869,8 +869,8 @@ name = "Slowpoke" desc = "The work of a truly genius gunsmith, altered and \"improved\" by a truly deranged Nanotrasen scientist, using components from a kinetic accelerator and beam rifle. Draw, partner!" icon = 'icons/obj/guns/energy.dmi' - lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + lefthand_file = GUN_LEFTHAND_ICON + righthand_file = GUN_RIGHTHAND_ICON icon_state = "spur" item_state = "spur" selfcharge = 1 diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index c15c4a1af835..4a768fc1c501 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -495,7 +495,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(isobserver(usr)) //Make sure they're an observer! - var/list/dest = list() //List of possible destinations (mobs) var/target = null //Chosen target. diff --git a/code/modules/mob/dead/observer/orbit.dm b/code/modules/mob/dead/observer/orbit.dm index 86d54577538c..da3bc7c2dfb5 100644 --- a/code/modules/mob/dead/observer/orbit.dm +++ b/code/modules/mob/dead/observer/orbit.dm @@ -57,7 +57,7 @@ var/list/misc = list() var/list/npcs = list() - var/list/pois = getpois(skip_mindless = TRUE, specify_dead_role = FALSE) + var/list/pois = getpois(skip_mindless = TRUE, specify_dead_role = FALSE, only_realname = TRUE) for (var/name in pois) var/list/serialized = list() serialized["name"] = name @@ -67,6 +67,8 @@ serialized["ref"] = REF(poi) var/mob/M = poi + + serialized["fake_name"] = M.name if (istype(M)) if (isobserver(M)) ghosts += list(serialized) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index f92e8d762f2d..7bbe9fb1de72 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -326,7 +326,7 @@ if(!key) msg += "[t_He] [t_is] totally catatonic. The stresses of life in deep-space must have been too much for [t_him]. Any recovery is unlikely.\n" else if(!client) - msg += "[t_He] appears to be suffering from SSD - Space Sleep Disorder. [t_He] may snap out of it at any time! Or maybe never. It's best to leave [t_him] be.\n" + msg += "[t_He] [t_has] been suffering from SSD - Space Sleep Disorder - for [trunc(((world.time - lastclienttime) / (1 MINUTES)))] minutes. [t_He] may snap out of it at any time! Or maybe never. It's best to leave [t_him] be.\n" if (length(msg)) . += "[msg.Join("")]" diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 1cb061ff9fd9..64dfdfde91ce 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -501,6 +501,10 @@ else if(!(flags & SHOCK_NOGLOVES)) //This gets the siemens_coeff for all non tesla shocks if(gloves) siemens_coeff *= gloves.siemens_coefficient + //If it doesnt have physiology its prob still initializing. + if(!physiology) + . = ..() + return siemens_coeff *= physiology.siemens_coeff siemens_coeff *= dna.species.siemens_coeff . = ..() diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 0fc21db37d8c..c5145600bbf8 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -25,9 +25,12 @@ if(.) //not dead handle_blood() - if(isLivingSSD())//if you're disconnected, you're going to sleep - if(AmountSleeping() < 20) - AdjustSleeping(20)//adjust every 10 seconds + if(isLivingSSD()) // If you're disconnected, you're going to sleep + if(trunc((world.time - lastclienttime) / (3 MINUTES)) > 0) // After a three minute grace period, your character will fall asleep + if(AmountSleeping() < 20) + AdjustSleeping(20) // Adjust every 10 seconds + if(ssd_indicator) + cut_overlay(GLOB.ssd_indicator_overlay) // Prevents chronically SSD players from breaking immersion if(stat != DEAD) var/bprv = handle_bodyparts() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 762706d9c855..1258df8b84c5 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1411,6 +1411,32 @@ if(player_logged && stat != DEAD) return TRUE +// The above code is kept to prevent old SSD behavior from breaking, while the code below is dedicated to the SSD Indicator + +GLOBAL_VAR_INIT(ssd_indicator_overlay, mutable_appearance('icons/mob/ssd_indicator.dmi', "default0", RUNECHAT_PLANE)) + +/mob/living + var/ssd_indicator = FALSE + var/lastclienttime = 0 + +/mob/living/proc/set_ssd_indicator(state) + if(state == ssd_indicator) + return + ssd_indicator = state + if(ssd_indicator && stat != DEAD) + add_overlay(GLOB.ssd_indicator_overlay) + else + cut_overlay(GLOB.ssd_indicator_overlay) + +/mob/living/Login() + . = ..() + set_ssd_indicator(FALSE) + +/mob/living/Logout() + . = ..() + lastclienttime = world.time + set_ssd_indicator(TRUE) + /mob/living/vv_get_header() . = ..() var/refid = REF(src) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/codename_claw.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/codename_claw.dm index 3a4506b62562..a762a9298279 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/codename_claw.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/codename_claw.dm @@ -232,7 +232,6 @@ projectiletype = /obj/projectile/tentacle projectilesound = 'sound/effects/splat.ogg' Shoot(target) - /////TENTACLE END /////STING ATTACK diff --git a/code/modules/projectiles/ammunition/_ammunition.dm b/code/modules/projectiles/ammunition/_ammunition.dm index 26597a64f33b..b216296cfe8d 100644 --- a/code/modules/projectiles/ammunition/_ammunition.dm +++ b/code/modules/projectiles/ammunition/_ammunition.dm @@ -32,7 +32,7 @@ var/pellets = 1 //Pellets for spreadshot var/variance = 0 //Variance for inaccuracy fundamental to the casing - var/randomspread = 0 //Randomspread for automatics + var/randomspread = FALSE //Randomspread for automatics var/delay = 0 //Delay for energy weapons var/click_cooldown_override = 0 //Override this to make your gun have a faster fire rate, in tenths of a second. 4 is the default gun cooldown. diff --git a/code/modules/projectiles/boxes_magazines/external/rifle.dm b/code/modules/projectiles/boxes_magazines/external/rifle.dm index 1066e5b7ef2d..9224c0db84af 100644 --- a/code/modules/projectiles/boxes_magazines/external/rifle.dm +++ b/code/modules/projectiles/boxes_magazines/external/rifle.dm @@ -56,7 +56,7 @@ multiple_sprites = AMMO_BOX_FULL_EMPTY /obj/item/ammo_box/magazine/skm_762_40/empty - start_empty = FALSE + start_empty = TRUE /obj/item/ammo_box/magazine/skm_762_40/extended name = "extended assault rifle magazine (7.62x40mm CLIP)" diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index b92b79e0009f..707f4805afe3 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -4,6 +4,8 @@ icon = 'icons/obj/guns/projectile.dmi' icon_state = "flatgun" item_state = "gun" + lefthand_file = GUN_LEFTHAND_ICON + righthand_file = GUN_RIGHTHAND_ICON flags_1 = CONDUCT_1 slot_flags = ITEM_SLOT_BELT custom_materials = list(/datum/material/iron=2000) @@ -16,101 +18,185 @@ attack_verb = list("struck", "hit", "bashed") pickup_sound = 'sound/items/handling/gun_pickup.ogg' drop_sound = 'sound/items/handling/gun_drop.ogg' + //trigger guard on the weapon, hulks can't fire them with their big meaty fingers + trigger_guard = TRIGGER_GUARD_NORMAL - /// The manufacturer of this weapon. For flavor mostly. If none, this will not show. + ///The manufacturer of this weapon. For flavor mostly. If none, this will not show. var/manufacturer = MANUFACTURER_NONE +/* + * Muzzle +*/ + ///Effect for the muzzle flash of the gun. + var/obj/effect/muzzle_flash/muzzle_flash + ///Icon state of the muzzle flash effect. + var/muzzleflash_iconstate + ///Brightness of the muzzle flash effect. + var/muzzle_flash_lum = 3 + ///Color of the muzzle flash effect. + var/muzzle_flash_color = COLOR_VERY_SOFT_YELLOW + +/* + * Firing +*/ var/fire_sound = 'sound/weapons/gun/pistol/shot.ogg' var/vary_fire_sound = TRUE var/fire_sound_volume = 50 var/dry_fire_sound = 'sound/weapons/gun/general/dry_fire.ogg' - ///Text showed when attempting to fire with no round or empty round. var/dry_fire_text = "click" - ///whether or not a message is displayed when fired - var/suppressed = null - var/can_suppress = FALSE + +/* + * Reloading +*/ + var/obj/item/ammo_casing/chambered = null + ///Whether the gun can be tacloaded by slapping a fresh magazine directly on it + var/tac_reloads = TRUE + ///If we have the 'snowflake mechanic,' how long should it take to reload? + var/tactical_reload_delay = 1 SECONDS + +//BALLISTIC + ///Compatible magazines with the gun + var/mag_type = /obj/item/ammo_box/magazine/m10mm //Removes the need for max_ammo and caliber info + ///Whether the gun alarms when empty or not. + var/empty_alarm = FALSE + ///Do we eject the magazine upon runing out of ammo? + var/empty_autoeject = FALSE + ///Whether the gun supports multiple special mag types + var/special_mags = FALSE + + ///Actual magazine currently contained within the gun + var/obj/item/ammo_box/magazine/magazine + ///whether the gun ejects the chambered casing + var/casing_ejector = TRUE + ///Whether the gun has an internal magazine or a detatchable one. Overridden by BOLT_TYPE_NO_BOLT. + var/internal_magazine = FALSE + + ///Phrasing of the magazine in examine and notification messages; ex: magazine, box, etx + var/magazine_wording = "magazine" + ///Phrasing of the cartridge in examine and notification messages; ex: bullet, shell, dart, etc. + var/cartridge_wording = "bullet" + + ///sound when inserting magazine + var/load_sound = 'sound/weapons/gun/general/magazine_insert_full.ogg' + ///sound when inserting an empty magazine + var/load_empty_sound = 'sound/weapons/gun/general/magazine_insert_empty.ogg' + ///volume of loading sound + var/load_sound_volume = 40 + ///whether loading sound should vary + var/load_sound_vary = TRUE + ///Sound of ejecting a magazine + var/eject_sound = 'sound/weapons/gun/general/magazine_remove_full.ogg' + ///sound of ejecting an empty magazine + var/eject_empty_sound = 'sound/weapons/gun/general/magazine_remove_empty.ogg' + ///volume of ejecting a magazine + var/eject_sound_volume = 40 + ///whether eject sound should vary + var/eject_sound_vary = TRUE + +//ENERGY + //What type of power cell this uses + var/obj/item/stock_parts/cell/gun/cell + var/cell_type = /obj/item/stock_parts/cell/gun + //Can it be charged in a recharger? + var/can_charge = TRUE + var/selfcharge = FALSE + var/charge_tick = 0 + var/charge_delay = 4 + //whether the gun's cell drains the cyborg user's cell to recharge + var/use_cyborg_cell = FALSE + ///Used for large and small cells + var/mag_size = MAG_SIZE_MEDIUM + //Time it takes to unscrew the cell + var/unscrewing_time = 2 SECONDS + + ///if the gun's cell cannot be replaced + var/internal_cell = FALSE + + var/list/ammo_type = list(/obj/item/ammo_casing/energy) + //The state of the select fire switch. Determines from the ammo_type list what kind of shot is fired next. + var/select = 1 + +/* + * Operation +*/ + //whether or not a message is displayed when fired + var/suppressed = FALSE var/suppressed_sound = 'sound/weapons/gun/general/heavy_shot_suppressed.ogg' var/suppressed_volume = 60 - var/can_unsuppress = TRUE - var/obj/item/ammo_casing/chambered = null - ///trigger guard on the weapon. Used for hulk mutations and ashies. I honestly dont know how usefult his is, id avoid touching it - trigger_guard = TRIGGER_GUARD_NORMAL - ///Set the description of the gun to this when sawed off - var/sawn_desc = null - ///This triggers some sprite behavior in shotguns and prevents further sawoff, note that can_be_sawn_off is on gun/ballistic and not here, wtf. - var/sawn_off = FALSE - /// how many shots per burst, Ex: most machine pistols, M90, some ARs are 3rnd burst, while others like the GAR and laser minigun are 2 round burst. - var/burst_size = 3 - ///The rate of fire when firing in a burst. Not the delay between bursts - var/burst_delay = 0.15 SECONDS - ///The rate of fire when firing full auto and semi auto, and between bursts; for bursts its fire delay + burst_delay after every burst - var/fire_delay = 0.2 SECONDS + //true if the gun is wielded via twohanded component, shouldnt affect anything else + var/wielded = FALSE + //true if the gun is wielded after delay, should affects accuracy + var/wielded_fully = FALSE + ///Slowdown for wielding + var/wield_slowdown = 0.1 + ///How long between wielding and firing in tenths of seconds + var/wield_delay = 0.4 SECONDS + ///Storing value for above + var/wield_time = 0 - /// after initializing, we set the firemode to this - var/default_firemode = FIREMODE_SEMIAUTO - ///Firemode index, due to code shit this is the currently selected firemode - var/firemode_index - /// Our firemodes, subtract and add to this list as needed. NOTE that the autofire component is given on init when FIREMODE_FULLAUTO is here. - var/list/gun_firemodes = list(FIREMODE_SEMIAUTO, FIREMODE_BURST, FIREMODE_FULLAUTO, FIREMODE_OTHER, FIREMODE_OTHER_TWO) - /// A acoc list that determines the names of firemodes. Use if you wanna be weird and set the name of say, FIREMODE_OTHER to "Underbarrel grenade launcher" for example. - var/list/gun_firenames = list(FIREMODE_SEMIAUTO = "single", FIREMODE_BURST = "burst fire", FIREMODE_FULLAUTO = "full auto", FIREMODE_OTHER = "misc. fire", FIREMODE_OTHER_TWO = "very misc. fire") - ///BASICALLY: the little button you select firing modes from? this is jsut the prefix of the icon state of that. For example, if we set it as "laser", the fire select will use "laser_single" and so on. - var/fire_select_icon_state_prefix = "" - ///If true, we put "safety_" before fire_select_icon_state_prefix's prefix. ex. "safety_laser_single" - var/adjust_fire_select_icon_state_on_safety = FALSE +// BALLISTIC + ///Whether the gun has to be racked each shot or not. + var/semi_auto = TRUE + ///The bolt type of the gun, affects quite a bit of functionality, see gun.dm in defines for bolt types: BOLT_TYPE_STANDARD; BOLT_TYPE_LOCKING; BOLT_TYPE_OPEN; BOLT_TYPE_NO_BOLT + var/bolt_type = BOLT_TYPE_STANDARD + ///Used for locking bolt and open bolt guns. Set a bit differently for the two but prevents firing when true for both. + var/bolt_locked = FALSE + ///Phrasing of the bolt in examine and notification messages; ex: bolt, slide, etc. + var/bolt_wording = "bolt" + ///length between individual racks + var/rack_delay = 5 + ///time of the most recent rack, used for cooldown purposes + var/recent_rack = 0 + + ///Whether the gun can be sawn off by sawing tools + var/can_be_sawn_off = FALSE + //description change if weapon is sawn-off + var/sawn_desc = null + var/sawn_off = FALSE - ///Are we firing a burst? If so, dont fire again until burst is done - var/currently_firing_burst = FALSE - ///This prevents gun from firing until the coodown is done, affected by lag - var/current_cooldown = 0 - ///affects if you can fire it unwielded or even dual wield it. LIGHT means dual wield allowed, HEAVY and higher means you have to wield to fire + ///sound of racking + var/rack_sound = 'sound/weapons/gun/general/bolt_rack.ogg' + ///volume of racking + var/rack_sound_volume = 60 + ///whether racking sound should vary + var/rack_sound_vary = TRUE + ///sound of when the bolt is locked back manually + var/lock_back_sound = 'sound/weapons/gun/general/slide_lock_1.ogg' + ///volume of lock back + var/lock_back_sound_volume = 60 + ///whether lock back varies + var/lock_back_sound_vary = TRUE + + ///sound of dropping the bolt or releasing a slide + var/bolt_drop_sound = 'sound/weapons/gun/general/bolt_drop.ogg' + ///volume of bolt drop/slide release + var/bolt_drop_sound_volume = 60 + ///empty alarm sound (if enabled) + var/empty_alarm_sound = 'sound/weapons/gun/general/empty_alarm.ogg' + ///empty alarm volume sound + var/empty_alarm_volume = 70 + ///whether empty alarm sound varies + var/empty_alarm_vary = TRUE + +/* + * Stats +*/ var/weapon_weight = WEAPON_LIGHT - ///If dual wielding, add this to the spread - var/dual_wield_spread = 24 - /// ???, no clue what this is. Original desc: //Set to 0 for shotguns. This is used for weapons that don't fire all their bullets at once. - var/randomspread = 1 - - ///Alters projectile damage multiplicatively based on this value. Use it for "better" or "worse" weapons that use the same ammo. + //Alters projectile damage multiplicatively based on this value. Use it for "better" or "worse" weapons that use the same ammo. var/projectile_damage_multiplier = 1 - - lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' - - var/list/attachment_options = list() //This.. works for now.. gun refactor soon - - var/can_flashlight = FALSE //if a flashlight can be added or removed if it already has one. - var/obj/item/flashlight/seclite/gun_light - var/datum/action/item_action/toggle_gunlight/alight - var/gunlight_state = "flight" - - var/can_bayonet = FALSE //if a bayonet can be added or removed if it already has one. - var/obj/item/kitchen/knife/bayonet - var/knife_x_offset = 0 - var/knife_y_offset = 0 - - var/ammo_x_offset = 0 //used for positioning ammo count overlay on sprite - var/ammo_y_offset = 0 - var/flight_x_offset = 0 - var/flight_y_offset = 0 - - //Zooming - var/zoomable = FALSE //whether the gun generates a Zoom action on creation - var/zoomed = FALSE //Zoom toggle - var/zoom_amt = 3 //Distance in TURFs to move the user's screen forward (the "zoom" effect) - var/zoom_out_amt = 0 - var/datum/action/toggle_scope_zoom/azoom - + //Speed someone can be flung if its point blank var/pb_knockback = 0 - var/wielded = FALSE // true if the gun is wielded via twohanded component, shouldnt affect anything else - - var/wielded_fully = FALSE // true if the gun is wielded after delay, should affects accuracy - + //Set to 0 for shotguns. This is used for weapons that don't fire all their bullets at once. + var/randomspread = TRUE ///How much the bullet scatters when fired while wielded. var/spread = 4 ///How much the bullet scatters when fired while unwielded. var/spread_unwielded = 12 + //additional spread when dual wielding + var/dual_wield_spread = 24 + ///Screen shake when the weapon is fired while wielded. var/recoil = 0 @@ -121,43 +207,126 @@ ///this is how much deviation the gun recoil can have, recoil pushes the screen towards the reverse angle you shot + some deviation which this is the max. var/recoil_deviation = 22.5 - ///Slowdown for wielding - var/wield_slowdown = 0.1 - ///How long between wielding and firing in tenths of seconds - var/wield_delay = 0.4 SECONDS - ///Storing value for above - var/wield_time = 0 + /// how many shots per burst, Ex: most machine pistols, M90, some ARs are 3rnd burst, while others like the GAR and laser minigun are 2 round burst. + var/burst_size = 3 + ///The rate of fire when firing in a burst. Not the delay between bursts + var/burst_delay = 0.15 SECONDS + ///The rate of fire when firing full auto and semi auto, and between bursts; for bursts its fire delay + burst_delay after every burst + var/fire_delay = 0.2 SECONDS + //Prevent the weapon from firing again while already firing + var/firing_burst = 0 - ///Effect for the muzzle flash of the gun. - var/obj/effect/muzzle_flash/muzzle_flash - ///Icon state of the muzzle flash effect. - var/muzzleflash_iconstate - ///Brightness of the muzzle flash effect. - var/muzzle_flash_lum = 3 - ///Color of the muzzle flash effect. - var/muzzle_flash_color = COLOR_VERY_SOFT_YELLOW +/* + * Overlay +*/ + ///Used for positioning ammo count overlay on sprite + var/ammo_x_offset = 0 + var/ammo_y_offset = 0 - //gun saftey +//BALLISTIC + ///Whether the sprite has a visible magazine or not + var/mag_display = FALSE + ///Whether the sprite has a visible ammo display or not + var/mag_display_ammo = FALSE + ///Whether the sprite has a visible indicator for being empty or not. + var/empty_indicator = FALSE + ///Whether the sprite has a visible magazine or not + var/show_magazine_on_sprite = FALSE + ///Whether the sprite has a visible ammo display or not + var/show_magazine_on_sprite_ammo = FALSE + ///Whether the gun supports multiple special mag types + var/unique_mag_sprites_for_variants = FALSE + +//ENERGY + //Do we handle overlays with base update_appearance()? + var/automatic_charge_overlays = TRUE + var/charge_sections = 4 + //if this gun uses a stateful charge bar for more detail + var/shaded_charge = FALSE + //Modifies WHOS state //im SOMEWHAT this is wether or not the overlay changes based on the ammo type selected + var/modifystate = TRUE + +/* + * Attachment +*/ + ///The types of attachments allowed, a list of types. SUBTYPES OF AN ALLOWED TYPE ARE ALSO ALLOWED + var/list/valid_attachments = list() + ///Reference to our attachment holder to prevent subtypes having to call GetComponent + var/datum/component/attachment_holder/attachment_holder + ///Number of attachments that can fit on a given slot + var/list/slot_available = ATTACHMENT_DEFAULT_SLOT_AVAILABLE + ///Offsets for the slots on this gun. should be indexed by SLOT and then by X/Y + var/list/slot_offsets = list() + +/* + * Zooming +*/ + ///Whether the gun generates a Zoom action on creation + var/zoomable = FALSE + //Zoom toggle + var/zoomed = FALSE + ///Distance in TURFs to move the user's screen forward (the "zoom" effect) + var/zoom_amt = 3 + var/zoom_out_amt = 0 + var/datum/action/toggle_scope_zoom/azoom + +/* + * Safety +*/ ///Does this gun have a saftey and thus can toggle it? var/has_safety = FALSE ///If the saftey on? If so, we can't fire the weapon var/safety = FALSE - ///The wording of safety. Useful for guns that have a non-standard safety system, like a revolver var/safety_wording = "safety" +/* + * Spawn Info (Stuff that becomes useless onces the gun is spawned, mostly here for mappers) +*/ + ///Attachments spawned on initialization. Should also be in valid attachments or it SHOULD(once i add that) fail + var/list/default_attachments = list() + +//BALLISTIC + ///Whether the gun will spawn loaded with a magazine + var/spawnwithmagazine = TRUE + +//ENERGY + //set to true so the gun is given an empty cell + var/dead_cell = FALSE + +// Need to sort + ///trigger guard on the weapon. Used for hulk mutations and ashies. I honestly dont know how usefult his is, id avoid touching it + trigger_guard = TRIGGER_GUARD_NORMAL + + /// after initializing, we set the firemode to this + var/default_firemode = FIREMODE_SEMIAUTO + ///Firemode index, due to code shit this is the currently selected firemode + var/firemode_index + /// Our firemodes, subtract and add to this list as needed. NOTE that the autofire component is given on init when FIREMODE_FULLAUTO is here. + var/list/gun_firemodes = list(FIREMODE_SEMIAUTO, FIREMODE_BURST, FIREMODE_FULLAUTO, FIREMODE_OTHER, FIREMODE_OTHER_TWO) + /// A acoc list that determines the names of firemodes. Use if you wanna be weird and set the name of say, FIREMODE_OTHER to "Underbarrel grenade launcher" for example. + var/list/gun_firenames = list(FIREMODE_SEMIAUTO = "single", FIREMODE_BURST = "burst fire", FIREMODE_FULLAUTO = "full auto", FIREMODE_OTHER = "misc. fire", FIREMODE_OTHER_TWO = "very misc. fire") + ///BASICALLY: the little button you select firing modes from? this is jsut the prefix of the icon state of that. For example, if we set it as "laser", the fire select will use "laser_single" and so on. + var/fire_select_icon_state_prefix = "" + ///If true, we put "safety_" before fire_select_icon_state_prefix's prefix. ex. "safety_laser_single" + var/adjust_fire_select_icon_state_on_safety = FALSE + + ///Are we firing a burst? If so, dont fire again until burst is done + var/currently_firing_burst = FALSE + ///This prevents gun from firing until the coodown is done, affected by lag + var/current_cooldown = 0 + /obj/item/gun/Initialize() . = ..() RegisterSignal(src, COMSIG_TWOHANDED_WIELD, PROC_REF(on_wield)) RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, PROC_REF(on_unwield)) - if(gun_light) - alight = new(src) muzzle_flash = new(src, muzzleflash_iconstate) build_zooming() build_firemodes() /obj/item/gun/ComponentInitialize() . = ..() + attachment_holder = AddComponent(/datum/component/attachment_holder, slot_available, valid_attachments, slot_offsets, default_attachments) AddComponent(/datum/component/two_handed) /// triggered on wield of two handed item @@ -196,16 +365,10 @@ user.remove_movespeed_modifier(/datum/movespeed_modifier/gun) /obj/item/gun/Destroy() - if(gun_light) - QDEL_NULL(gun_light) - if(bayonet) - QDEL_NULL(bayonet) if(chambered) //Not all guns are chambered (EMP'ed energy guns etc) QDEL_NULL(chambered) if(azoom) QDEL_NULL(azoom) - if(isatom(suppressed)) //SUPPRESSED IS USED AS BOTH A TRUE/FALSE AND AS A REF, WHAT THE FUCKKKKKKKKKKKKKKKKK - QDEL_NULL(suppressed) if(muzzle_flash) QDEL_NULL(muzzle_flash) return ..() @@ -213,36 +376,17 @@ /obj/item/gun/handle_atom_del(atom/A) if(A == chambered) chambered = null - update_appearance() - if(A == bayonet) - clear_bayonet() - if(A == gun_light) - clear_gunlight() + update_icon() return ..() /obj/item/gun/examine(mob/user) . = ..() - if(gun_light) - . += "It has \a [gun_light] [can_flashlight ? "" : "permanently "]mounted on it." - if(can_flashlight) //if it has a light and this is false, the light is permanent. - . += "[gun_light] looks like it can be unscrewed from [src]." - else if(can_flashlight) - . += "It has a mounting point for a seclite." - - if(bayonet) - . += "It has \a [bayonet] [can_bayonet ? "" : "permanently "]affixed to it." - if(can_bayonet) //if it has a bayonet and this is false, the bayonet is permanent. - . += "[bayonet] looks like it can be unscrewed from [src]." - else if(can_bayonet) - . += "It has a bayonet lug on it." - if(has_safety) . += "The safety is [safety ? "ON" : "OFF"]. Ctrl-Click to toggle the safety." if(manufacturer) . += "It has [manufacturer] engraved on it." - /obj/item/gun/equipped(mob/living/user, slot) . = ..() if(zoomed && user.get_active_held_item() != src) @@ -250,48 +394,8 @@ /obj/item/gun/attack(mob/M as mob, mob/user) if(user.a_intent == INTENT_HARM) //Flogging - if(bayonet) - M.attackby(bayonet, user) - return - else - return ..() - return - -/obj/item/gun/attack_obj(obj/O, mob/user) - if(user.a_intent == INTENT_HARM) - if(bayonet) - O.attackby(bayonet, user) - return - return ..() - -/obj/item/gun/attackby(obj/item/I, mob/user, params) - if(user.a_intent == INTENT_HARM) - return ..() - else if(istype(I, /obj/item/flashlight/seclite)) - if(!can_flashlight) - return ..() - var/obj/item/flashlight/seclite/S = I - if(!gun_light) - if(!user.transferItemToLoc(I, src)) - return - to_chat(user, "You click [S] into place on [src].") - set_gun_light(S) - update_gunlight() - alight = new(src) - if(loc == user) - alight.Grant(user) - else if(istype(I, /obj/item/kitchen/knife)) - var/obj/item/kitchen/knife/K = I - if(!can_bayonet || !K.bayonet || bayonet) //ensure the gun has an attachment point available, and that the knife is compatible with it. - return ..() - if(!user.transferItemToLoc(I, src)) - return - to_chat(user, "You attach [K] to [src]'s bayonet lug.") - bayonet = K - update_appearance() - - else return ..() + return //called after the gun has successfully fired its chambered ammo. /obj/item/gun/proc/process_chamber(atom/shooter) @@ -513,6 +617,7 @@ /obj/item/gun/proc/reset_current_cooldown() current_cooldown = FALSE + /obj/item/gun/proc/shoot_with_empty_chamber(mob/living/user as mob|obj) if(!safety) to_chat(user, "*[dry_fire_text]*") @@ -600,116 +705,6 @@ update_appearance() - -/obj/item/gun/screwdriver_act(mob/living/user, obj/item/I) - . = ..() - if(.) - return - if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) - return - attachment_options = list() - get_gun_attachments() - if(LAZYLEN(attachment_options) == 1) - remove_gun_attachments(user, I, attachment_options[1]) - else if (LAZYLEN(attachment_options)) - var/picked_option = show_radial_menu(user, src, attachment_options, radius = 38, require_near = TRUE) - remove_gun_attachments(user, I, picked_option) - -/obj/item/gun/proc/get_gun_attachments() - if(can_flashlight && gun_light) - attachment_options += list("Light" = image(icon = gun_light.icon, icon_state = gun_light.icon_state)) - if(can_bayonet && bayonet) - attachment_options += list("Knife" = image(icon = bayonet.icon, icon_state = bayonet.icon_state)) - -/obj/item/gun/proc/remove_gun_attachments(mob/living/user, obj/item/I, picked_option) - if(picked_option == "Light") - return remove_gun_attachment(user, I, gun_light, "unscrewed") - else if(picked_option == "Knife") - return remove_gun_attachment(user, I, bayonet, "unfix") - -/obj/item/gun/proc/remove_gun_attachment(mob/living/user, obj/item/tool_item, obj/item/item_to_remove, removal_verb) - if(tool_item) - tool_item.play_tool_sound(src) - to_chat(user, "You [removal_verb ? removal_verb : "remove"] [item_to_remove] from [src].") - item_to_remove.forceMove(drop_location()) - - if(Adjacent(user) && !issilicon(user)) - user.put_in_hands(item_to_remove) - - if(item_to_remove == bayonet) - return clear_bayonet() - else if(item_to_remove == gun_light) - return clear_gunlight() - -/obj/item/gun/proc/clear_bayonet() - if(!bayonet) - return - bayonet = null - update_appearance() - return TRUE - -/obj/item/gun/proc/clear_gunlight() - if(!gun_light) - return - var/obj/item/flashlight/seclite/removed_light = gun_light - set_gun_light(null) - update_gunlight() - removed_light.update_brightness() - QDEL_NULL(alight) - return TRUE - -/** - * Swaps the gun's seclight, dropping the old seclight if it has not been qdel'd. - * - * Returns the former gun_light that has now been replaced by this proc. - * Arguments: - * * new_light - The new light to attach to the weapon. Can be null, which will mean the old light is removed with no replacement. - */ -/obj/item/gun/proc/set_gun_light(obj/item/flashlight/seclite/new_light) - // Doesn't look like this should ever happen? We're replacing our old light with our old light? - if(gun_light == new_light) - CRASH("Tried to set a new gun light when the old gun light was also the new gun light.") - - . = gun_light - - // If there's an old gun light that isn't being QDELETED, detatch and drop it to the floor. - if(!QDELETED(gun_light)) - gun_light.set_light_flags(gun_light.light_flags & ~LIGHT_ATTACHED) - if(gun_light.loc != get_turf(src)) - gun_light.forceMove(get_turf(src)) - - // If there's a new gun light to be added, attach and move it to the gun. - if(new_light) - new_light.set_light_flags(new_light.light_flags | LIGHT_ATTACHED) - if(new_light.loc != src) - new_light.forceMove(src) - - gun_light = new_light - -/obj/item/gun/ui_action_click(mob/user, actiontype) - if(istype(actiontype, alight)) - toggle_gunlight() - else - ..() - -/obj/item/gun/proc/toggle_gunlight() - if(!gun_light) - return - - var/mob/living/carbon/human/user = usr - gun_light.on = !gun_light.on - gun_light.update_brightness() - to_chat(user, "You toggle the gunlight [gun_light.on ? "on":"off"].") - - playsound(user, gun_light.on ? gun_light.toggle_on_sound : gun_light.toggle_off_sound, 40, TRUE) - update_gunlight() - -/obj/item/gun/proc/update_gunlight() - update_appearance() - for(var/X in actions) - var/datum/action/A = X - A.UpdateButtonIcon() - /obj/item/gun/attack_hand(mob/user) . = ..() update_appearance() @@ -730,27 +725,6 @@ /obj/item/gun/update_overlays() . = ..() - if(gun_light) - var/mutable_appearance/flashlight_overlay - var/state = "[gunlight_state][gun_light.on? "_on":""]" //Generic state. - if(gun_light.icon_state in icon_states('icons/obj/guns/flashlights.dmi')) //Snowflake state? - state = gun_light.icon_state - flashlight_overlay = mutable_appearance('icons/obj/guns/flashlights.dmi', state) - flashlight_overlay.pixel_x = flight_x_offset - flashlight_overlay.pixel_y = flight_y_offset - . += flashlight_overlay - - if(bayonet) - var/mutable_appearance/knife_overlay - var/state = "bayonet" //Generic state. - if(bayonet.icon_state in icon_states('icons/obj/guns/bayonets.dmi')) //Snowflake state? - state = bayonet.icon_state - var/icon/bayonet_icons = 'icons/obj/guns/bayonets.dmi' - knife_overlay = mutable_appearance(bayonet_icons, state) - knife_overlay.pixel_x = knife_x_offset - knife_overlay.pixel_y = knife_y_offset - . += knife_overlay - if(ismob(loc) && has_safety) var/mutable_appearance/safety_overlay safety_overlay = mutable_appearance('icons/obj/guns/safety.dmi') @@ -987,10 +961,7 @@ flash_loc.vis_contents -= muzzle_flash muzzle_flash.applied = FALSE -///////////// -// ZOOMING // -///////////// - +//I need to refactor this into an attachment /datum/action/toggle_scope_zoom name = "Toggle Scope" check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_HANDS_BLOCKED|AB_CHECK_IMMOBILE|AB_CHECK_LYING diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index a4247898d59d..7c75d8fe9f56 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -13,90 +13,26 @@ has_safety = TRUE safety = TRUE - ///sound when inserting magazine - var/load_sound = 'sound/weapons/gun/general/magazine_insert_full.ogg' - ///sound when inserting an empty magazine - var/load_empty_sound = 'sound/weapons/gun/general/magazine_insert_empty.ogg' - ///volume of loading sound - var/load_sound_volume = 40 - ///whether loading sound should vary - var/load_sound_vary = TRUE - ///sound of racking - var/rack_sound = 'sound/weapons/gun/general/bolt_rack.ogg' - ///volume of racking - var/rack_sound_volume = 60 - ///whether racking sound should vary - var/rack_sound_vary = TRUE - ///sound of when the bolt is locked back manually - var/lock_back_sound = 'sound/weapons/gun/general/slide_lock_1.ogg' - ///volume of lock back - var/lock_back_sound_volume = 60 - ///whether lock back varies - var/lock_back_sound_vary = TRUE - ///Sound of ejecting a magazine - var/eject_sound = 'sound/weapons/gun/general/magazine_remove_full.ogg' - ///sound of ejecting an empty magazine - var/eject_empty_sound = 'sound/weapons/gun/general/magazine_remove_empty.ogg' - ///volume of ejecting a magazine - var/eject_sound_volume = 40 - ///whether eject sound should vary - var/eject_sound_vary = TRUE - ///sound of dropping the bolt or releasing a slide - var/bolt_drop_sound = 'sound/weapons/gun/general/bolt_drop.ogg' - ///volume of bolt drop/slide release - var/bolt_drop_sound_volume = 60 - ///empty alarm sound (if enabled) - var/empty_alarm_sound = 'sound/weapons/gun/general/empty_alarm.ogg' - ///empty alarm volume sound - var/empty_alarm_volume = 70 - ///whether empty alarm sound varies - var/empty_alarm_vary = TRUE - - ///Whether the gun will spawn loaded with a magazine - var/spawnwithmagazine = TRUE - ///Compatible magazines with the gun - var/mag_type = /obj/item/ammo_box/magazine/m10mm //Removes the need for max_ammo and caliber info - ///Whether the sprite has a visible magazine or not - var/show_magazine_on_sprite = FALSE - ///Whether the sprite has a visible ammo display or not - var/show_magazine_on_sprite_ammo = FALSE - ///Whether the sprite has a visible indicator for being empty or not. - var/empty_indicator = FALSE - ///Whether the gun alarms when empty or not. - var/empty_alarm = FALSE - ///Do we eject the magazine upon runing out of ammo? - var/empty_autoeject = FALSE - ///Whether the gun supports multiple special mag types - var/unique_mag_sprites_for_variants = FALSE - ///The bolt type of the gun, affects quite a bit of functionality, see combat.dm defines for bolt types: BOLT_TYPE_STANDARD; BOLT_TYPE_LOCKING; BOLT_TYPE_OPEN; BOLT_TYPE_NO_BOLT - var/bolt_type = BOLT_TYPE_STANDARD - ///Used for locking bolt and open bolt guns. Set a bit differently for the two but prevents firing when true for both. - var/bolt_locked = FALSE - ///Whether the gun has to be racked each shot or not. - var/semi_auto = TRUE - ///Actual magazine currently contained within the gun - var/obj/item/ammo_box/magazine/magazine - ///whether the gun ejects the chambered casing - var/casing_ejector = TRUE - ///Whether the gun has an internal magazine or a detatchable one. Overridden by BOLT_TYPE_NO_BOLT. - var/internal_magazine = FALSE - ///Phrasing of the bolt in examine and notification messages; ex: bolt, slide, etc. - var/bolt_wording = "bolt" - ///Phrasing of the magazine in examine and notification messages; ex: magazine, box, etx - var/magazine_wording = "magazine" - ///Phrasing of the cartridge in examine and notification messages; ex: bullet, shell, dart, etc. - var/cartridge_wording = "bullet" - ///length between individual racks - var/rack_delay = 5 - ///time of the most recent rack, used for cooldown purposes - var/recent_rack = 0 - ///Whether the gun can be sawn off by sawing tools - var/can_be_sawn_off = FALSE - - ///Whether the gun can be tacloaded by slapping a fresh magazine directly on it - var/tac_reloads = TRUE //Snowflake mechanic no more. - ///If we have the 'snowflake mechanic,' how long should it take to reload? - var/tactical_reload_delay = 1 SECONDS + valid_attachments = list( + /obj/item/attachment/silencer, + /obj/item/attachment/laser_sight, + /obj/item/attachment/rail_light, + /obj/item/attachment/bayonet + ) + slot_available = list( + ATTACHMENT_SLOT_MUZZLE = 1, + ATTACHMENT_SLOT_RAIL = 1 + ) + slot_offsets = list( + ATTACHMENT_SLOT_MUZZLE = list( + "x" = 26, + "y" = 20, + ), + ATTACHMENT_SLOT_RAIL = list( + "x" = 19, + "y" = 18, + ) + ) /obj/item/gun/ballistic/Initialize() . = ..() @@ -123,8 +59,6 @@ . += "[icon_state]_bolt[bolt_locked ? "_locked" : ""]" if (bolt_type == BOLT_TYPE_OPEN && bolt_locked) . += "[icon_state]_bolt" - if (suppressed) - . += "[icon_state]_suppressor" if (magazine) if (unique_mag_sprites_for_variants) . += "[icon_state]_mag_[magazine.base_icon_state]" @@ -203,12 +137,12 @@ update_appearance() ///Handles all the logic needed for magazine insertion -/obj/item/gun/ballistic/proc/insert_magazine(mob/user, obj/item/ammo_box/magazine/AM, display_message = TRUE) - if(!istype(AM, mag_type)) - to_chat(user, "\The [AM] doesn't seem to fit into \the [src]...") +/obj/item/gun/ballistic/proc/insert_magazine(mob/user, obj/item/ammo_box/magazine/inserted_mag, display_message = TRUE) + if(!istype(inserted_mag, mag_type)) + to_chat(user, "\The [inserted_mag] doesn't seem to fit into \the [src]...") return FALSE - if(user.transferItemToLoc(AM, src)) - magazine = AM + if(user.transferItemToLoc(inserted_mag, src)) + magazine = inserted_mag if (display_message) to_chat(user, "You load a new [magazine_wording] into \the [src].") if (magazine.ammo_count()) @@ -287,48 +221,11 @@ A.update_appearance() update_appearance() return - if(istype(A, /obj/item/suppressor)) - var/obj/item/suppressor/S = A - if(!can_suppress) - to_chat(user, "You can't seem to figure out how to fit [S] on [src]!") - return - if(!user.is_holding(src)) - to_chat(user, "You need be holding [src] to fit [S] to it!") - return - if(suppressed) - to_chat(user, "[src] already has a suppressor!") - return - if(user.transferItemToLoc(A, src)) - to_chat(user, "You screw \the [S] onto \the [src].") - install_suppressor(A) - return if (can_be_sawn_off) if (sawoff(user, A)) return return FALSE -///Installs a new suppressor, assumes that the suppressor is already in the contents of src -/obj/item/gun/ballistic/proc/install_suppressor(obj/item/suppressor/S) - suppressed = S - w_class += S.w_class //so pistols do not fit in pockets when suppressed - update_appearance() - -/obj/item/gun/ballistic/AltClick(mob/user) - if (unique_reskin && !current_skin && user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY)) - reskin_obj(user) - return - if(loc == user) - if(suppressed && can_unsuppress) - var/obj/item/suppressor/S = suppressed - if(!user.is_holding(src)) - return ..() - to_chat(user, "You unscrew \the [suppressed] from \the [src].") - user.put_in_hands(suppressed) - w_class -= S.w_class - suppressed = null - update_appearance() - return - ///Prefire empty checks for the bolt drop /obj/item/gun/ballistic/proc/prefire_empty_checks() if (!chambered && !get_ammo()) @@ -402,9 +299,7 @@ . += "It does not seem to have a round chambered." if (bolt_locked) . += "The [bolt_wording] is locked back and needs to be released before firing." - if (suppressed) - . += "It has a suppressor attached that can be removed with alt+click." - . += "You can [bolt_wording] [src] by pressing the unique action key. By default, this is space" + . += "You can [bolt_wording] [src] by pressing the unqiue action key. By default, this is space" ///Gets the number of bullets in the gun /obj/item/gun/ballistic/proc/get_ammo(countchambered = TRUE) @@ -437,9 +332,6 @@ GLOBAL_LIST_INIT(gun_saw_types, typecacheof(list( if(sawn_off) to_chat(user, "\The [src] is already shortened!") return - if(bayonet) - to_chat(user, "You cannot saw-off \the [src] with \the [bayonet] attached!") - return user.changeNext_move(CLICK_CD_MELEE) user.visible_message("[user] begins to shorten \the [src].", "You begin to shorten \the [src]...") @@ -470,16 +362,3 @@ GLOBAL_LIST_INIT(gun_saw_types, typecacheof(list( if(AC.BB) process_fire(user, user, FALSE) . = TRUE - - -/obj/item/suppressor - name = "suppressor" - desc = "A syndicate small-arms suppressor for maximum espionage." - icon = 'icons/obj/guns/projectile.dmi' - icon_state = "suppressor" - w_class = WEIGHT_CLASS_TINY - - -/obj/item/suppressor/specialoffer - name = "cheap suppressor" - desc = "A foreign knock-off suppressor, it feels flimsy, cheap, and brittle. Still fits most weapons." diff --git a/code/modules/projectiles/guns/ballistic/assault.dm b/code/modules/projectiles/guns/ballistic/assault.dm index 3f649994827e..ce500cda930b 100644 --- a/code/modules/projectiles/guns/ballistic/assault.dm +++ b/code/modules/projectiles/guns/ballistic/assault.dm @@ -164,7 +164,6 @@ icon_state = "e40" item_state = "e40" mag_type = /obj/item/ammo_box/magazine/e40 - can_suppress = FALSE var/obj/item/gun/energy/laser/e40_laser_secondary/secondary fire_select_icon_state_prefix = "e40_" diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm index 2fea717c28a0..769ea9e7f57e 100644 --- a/code/modules/projectiles/guns/ballistic/automatic.dm +++ b/code/modules/projectiles/guns/ballistic/automatic.dm @@ -1,7 +1,6 @@ /obj/item/gun/ballistic/automatic w_class = WEIGHT_CLASS_NORMAL - can_suppress = TRUE gun_firemodes = list(FIREMODE_SEMIAUTO) default_firemode = FIREMODE_SEMIAUTO @@ -33,8 +32,6 @@ mag_type = /obj/item/ammo_box/magazine/m10mm/rifle fire_delay = 0.5 SECONDS burst_size = 1 - can_unsuppress = TRUE - can_suppress = TRUE w_class = WEIGHT_CLASS_HUGE slot_flags = ITEM_SLOT_BACK show_magazine_on_sprite = TRUE @@ -48,7 +45,6 @@ item_state = "arg" mag_type = /obj/item/ammo_box/magazine/recharge fire_delay = 0.2 SECONDS - can_suppress = FALSE burst_size = 0 fire_sound = 'sound/weapons/laser.ogg' casing_ejector = FALSE @@ -59,8 +55,6 @@ icon_state = "ZipPistol" item_state = "ZipPistol" mag_type = /obj/item/ammo_box/magazine/zip_ammo_9mm - can_suppress = FALSE actions_types = list() - can_bayonet = FALSE show_magazine_on_sprite = TRUE weapon_weight = WEAPON_LIGHT diff --git a/code/modules/projectiles/guns/ballistic/gauss.dm b/code/modules/projectiles/guns/ballistic/gauss.dm index 12264a3ccd8f..3fdc2e55dadd 100644 --- a/code/modules/projectiles/guns/ballistic/gauss.dm +++ b/code/modules/projectiles/guns/ballistic/gauss.dm @@ -11,7 +11,6 @@ mag_type = /obj/item/ammo_box/magazine/gauss fire_sound = 'sound/weapons/gun/gauss/magrifle.ogg' load_sound = 'sound/weapons/gun/gauss/rifle_reload.ogg' - can_suppress = FALSE burst_size = 1 fire_delay = 0.3 SECONDS spread = 0 diff --git a/code/modules/projectiles/guns/ballistic/hmg.dm b/code/modules/projectiles/guns/ballistic/hmg.dm index 79977249dd31..8a3e68b9a6ec 100644 --- a/code/modules/projectiles/guns/ballistic/hmg.dm +++ b/code/modules/projectiles/guns/ballistic/hmg.dm @@ -163,7 +163,6 @@ base_icon_state = "l6" mag_type = /obj/item/ammo_box/magazine/mm712x82 - can_suppress = FALSE spread = 7 fire_delay = 0.1 SECONDS @@ -236,8 +235,6 @@ fire_select_icon_state_prefix = "caseless_" - can_suppress = FALSE - can_bayonet = FALSE show_magazine_on_sprite = TRUE w_class = WEIGHT_CLASS_BULKY manufacturer = MANUFACTURER_SOLARARMORIES diff --git a/code/modules/projectiles/guns/ballistic/launchers.dm b/code/modules/projectiles/guns/ballistic/launchers.dm index d82f2dbd1250..f18f97cd0f4f 100644 --- a/code/modules/projectiles/guns/ballistic/launchers.dm +++ b/code/modules/projectiles/guns/ballistic/launchers.dm @@ -55,7 +55,6 @@ fire_sound = 'sound/weapons/gun/general/rocket_launch.ogg' load_sound = 'sound/weapons/gun/general/rocket_load.ogg' w_class = WEIGHT_CLASS_BULKY - can_suppress = FALSE burst_size = 1 fire_delay = 0.4 SECONDS casing_ejector = FALSE diff --git a/code/modules/projectiles/guns/ballistic/pistol.dm b/code/modules/projectiles/guns/ballistic/pistol.dm index 347f4950382e..b2416462da39 100644 --- a/code/modules/projectiles/guns/ballistic/pistol.dm +++ b/code/modules/projectiles/guns/ballistic/pistol.dm @@ -1,5 +1,4 @@ /obj/item/gun/ballistic/automatic/pistol - can_suppress = TRUE bolt_type = BOLT_TYPE_LOCKING vary_fire_sound = FALSE @@ -67,7 +66,6 @@ EMPTY_GUN_HELPER(automatic/pistol/syndicate) mob_overlay_icon = 'icons/obj/guns/manufacturer/hunterspride/onmob.dmi' mag_type = /obj/item/ammo_box/magazine/m45 - can_suppress = FALSE fire_sound = 'sound/weapons/gun/pistol/candor.ogg' rack_sound = 'sound/weapons/gun/pistol/candor_cocked.ogg' lock_back_sound = 'sound/weapons/gun/pistol/slide_lock.ogg' @@ -106,7 +104,7 @@ EMPTY_GUN_HELPER(automatic/pistol/candor/factory) icon_state = "deagle" force = 14 mag_type = /obj/item/ammo_box/magazine/m50 - can_suppress = FALSE + mag_display = TRUE show_magazine_on_sprite = TRUE fire_sound = 'sound/weapons/gun/pistol/deagle.ogg' rack_sound = 'sound/weapons/gun/pistol/rack.ogg' @@ -166,7 +164,6 @@ EMPTY_GUN_HELPER(automatic/pistol/candor/factory) gun_firemodes = list(FIREMODE_SEMIAUTO, FIREMODE_BURST) default_firemode = FIREMODE_SEMIAUTO - /obj/item/gun/ballistic/automatic/pistol/commander name = "\improper Commander" desc = "A classic handgun in a tasteful black and stainless steel color scheme. An enamel Nanotrasen logo is set into the grips. Chambered in 9mm." @@ -178,7 +175,6 @@ EMPTY_GUN_HELPER(automatic/pistol/candor/factory) w_class = WEIGHT_CLASS_NORMAL mag_type = /obj/item/ammo_box/magazine/co9mm - can_suppress = FALSE manufacturer = MANUFACTURER_NANOTRASEN fire_sound = 'sound/weapons/gun/pistol/commander.ogg' load_sound = 'sound/weapons/gun/pistol/mag_insert.ogg' @@ -216,7 +212,6 @@ EMPTY_GUN_HELPER(automatic/pistol/commander/inteq) w_class = WEIGHT_CLASS_NORMAL mag_type = /obj/item/ammo_box/magazine/co9mm - can_suppress = FALSE var/funnysounds = TRUE var/cooldown = 0 load_sound = 'sound/weapons/gun/pistol/mag_insert.ogg' @@ -256,6 +251,7 @@ EMPTY_GUN_HELPER(automatic/pistol/commander/inteq) to_chat(user, "You toggle [src]'s vox audio functions.") /obj/item/gun/ballistic/automatic/pistol/commissar/AltClick(mob/user) + . = ..() if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user))) return if((cooldown < world.time - 200) && funnysounds) @@ -327,7 +323,6 @@ EMPTY_GUN_HELPER(automatic/pistol/commander/inteq) w_class = WEIGHT_CLASS_NORMAL mag_type = /obj/item/ammo_box/magazine/disposable custom_materials = list(/datum/material/plastic=2000) - can_suppress = FALSE manufacturer = MANUFACTURER_NONE has_safety = FALSE //thing barely costs anything, why would it have a safety? safety = FALSE @@ -410,7 +405,6 @@ EMPTY_GUN_HELPER(automatic/pistol/commander/inteq) w_class = WEIGHT_CLASS_TINY mag_type = /obj/item/ammo_box/magazine/m22lr - can_suppress = FALSE fire_sound = 'sound/weapons/gun/pistol/himehabu.ogg' load_sound = 'sound/weapons/gun/pistol/mag_insert_alt.ogg' diff --git a/code/modules/projectiles/guns/ballistic/rifle.dm b/code/modules/projectiles/guns/ballistic/rifle.dm index 4cf82a445fb3..1e7724c5c9fa 100644 --- a/code/modules/projectiles/guns/ballistic/rifle.dm +++ b/code/modules/projectiles/guns/ballistic/rifle.dm @@ -99,7 +99,6 @@ if(.) spread = 24 spread_unwielded = 30 - can_bayonet = FALSE item_state = "illestren_sawn" mob_overlay_state = item_state weapon_weight = WEAPON_MEDIUM //you can fire it onehanded, makes it worse than worse than useless onehanded, but you can diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm index 9dba3399fcbd..1f15f8d01689 100644 --- a/code/modules/projectiles/guns/ballistic/shotgun.dm +++ b/code/modules/projectiles/guns/ballistic/shotgun.dm @@ -78,7 +78,7 @@ fire_delay = 0.05 SECONDS //slamfire rack_delay = 0.2 SECONDS - can_be_sawn_off = TRUE + can_be_sawn_off = TRUE /obj/item/gun/ballistic/shotgun/brimstone/sawoff(mob/user) @@ -111,7 +111,7 @@ mag_type = /obj/item/ammo_box/magazine/internal/shot/riot sawn_desc = "Come with me if you want to live." - can_be_sawn_off = TRUE + can_be_sawn_off = TRUE rack_sound = 'sound/weapons/gun/shotgun/rack_alt.ogg' fire_delay = 0.1 SECONDS @@ -141,8 +141,6 @@ recoil = 1 recoil_unwielded = 4 wield_delay = 0.65 SECONDS - -/obj/item/gun/ballistic/shotgun/automatic manufacturer = MANUFACTURER_NANOTRASEN /obj/item/gun/ballistic/shotgun/automatic/shoot_live_shot(mob/living/user) @@ -232,7 +230,6 @@ weapon_weight = WEAPON_MEDIUM mag_type = /obj/item/ammo_box/magazine/m12g - can_suppress = FALSE burst_size = 1 fire_delay = 0.4 SECONDS // this NEEDS the old delay. fire_sound = 'sound/weapons/gun/shotgun/bulldog.ogg' @@ -332,7 +329,7 @@ EMPTY_GUN_HELPER(shotgun/bulldog/inteq) "Stained Green" = "dshotgun_green" ) semi_auto = TRUE - can_be_sawn_off = TRUE + can_be_sawn_off = TRUE bolt_type = BOLT_TYPE_NO_BOLT pb_knockback = 3 // it's a super shotgun! manufacturer = MANUFACTURER_HUNTERSPRIDE @@ -452,8 +449,8 @@ EMPTY_GUN_HELPER(shotgun/bulldog/inteq) name = "improvised shotgun" desc = "A length of pipe and miscellaneous bits of scrap fashioned into a rudimentary single-shot shotgun." icon = 'icons/obj/guns/projectile.dmi' - lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + lefthand_file = GUN_LEFTHAND_ICON + righthand_file = GUN_RIGHTHAND_ICON mob_overlay_icon = null base_icon_state = "ishotgun" @@ -519,7 +516,7 @@ EMPTY_GUN_HELPER(shotgun/bulldog/inteq) mag_type = /obj/item/ammo_box/magazine/internal/shot/com/compact/compact w_class = WEIGHT_CLASS_SMALL sawn_desc = "You know, this isn't funny anymore." - can_be_sawn_off = TRUE + can_be_sawn_off = TRUE /obj/item/gun/ballistic/shotgun/automatic/combat/compact/compact/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0) if(prob(0 + (magazine.ammo_count() * 20))) //minimum probability of 20, maximum of 60 @@ -542,7 +539,7 @@ EMPTY_GUN_HELPER(shotgun/bulldog/inteq) mag_type = /obj/item/ammo_box/magazine/internal/shot/com/compact/compact/compact w_class = WEIGHT_CLASS_TINY sawn_desc = "Sigh. This is a trigger attached to a bullet." - can_be_sawn_off = TRUE + can_be_sawn_off = TRUE /obj/item/gun/ballistic/shotgun/automatic/combat/compact/compact/compact/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0) if(prob(50)) //It's going to blow up. @@ -636,7 +633,7 @@ EMPTY_GUN_HELPER(shotgun/bulldog/inteq) rack_sound = 'sound/weapons/gun/rifle/skm_cocked.ogg' bolt_wording = "lever" cartridge_wording = "bullet" - can_be_sawn_off = TRUE + can_be_sawn_off = TRUE wield_slowdown = 0.5 wield_delay = 0.65 SECONDS @@ -765,15 +762,12 @@ EMPTY_GUN_HELPER(shotgun/bulldog/inteq) inhand_y_dimension = 32 mag_type = /obj/item/ammo_box/magazine/internal/shot/beacon fire_sound = 'sound/weapons/gun/revolver/shot_hunting.ogg' - can_be_sawn_off=TRUE w_class = WEIGHT_CLASS_BULKY weapon_weight = WEAPON_MEDIUM force = 10 - flags_1 = CONDUCT_1 - slot_flags = ITEM_SLOT_BACK obj_flags = UNIQUE_RENAME semi_auto = TRUE - can_be_sawn_off = TRUE + can_be_sawn_off = TRUE pb_knockback = 3 wield_slowdown = 0.7 spread_unwielded = 15 @@ -797,7 +791,7 @@ EMPTY_GUN_HELPER(shotgun/bulldog/inteq) recoil = 2 recoil_unwielded = 4 -/obj/item/gun/ballistic/shotgun/doublebarrel/beacon +/obj/item/gun/ballistic/shotgun/doublebarrel/beacon/no_mag spawnwithmagazine = FALSE /obj/item/gun/ballistic/shotgun/doublebarrel/beacon/factory diff --git a/code/modules/projectiles/guns/ballistic/smg.dm b/code/modules/projectiles/guns/ballistic/smg.dm index 96d4e7d922db..2cb68fc09176 100644 --- a/code/modules/projectiles/guns/ballistic/smg.dm +++ b/code/modules/projectiles/guns/ballistic/smg.dm @@ -50,10 +50,6 @@ item_state = "c20r" mag_type = /obj/item/ammo_box/magazine/smgm45 - can_bayonet = TRUE - can_suppress = FALSE - knife_x_offset = 26 - knife_y_offset = 12 show_magazine_on_sprite = TRUE show_magazine_on_sprite_ammo = TRUE empty_indicator = TRUE @@ -68,7 +64,6 @@ EMPTY_GUN_HELPER(automatic/smg/c20r) /obj/item/gun/ballistic/automatic/smg/c20r/cobra name = "\improper Cobra 20" desc = "An older model of SMG manufactured by Scarborough Arms, a predecessor to the military C-20 series. Chambered in .45. " - can_bayonet = FALSE icon_state = "cobra20" item_state = "cobra20" @@ -90,11 +85,7 @@ EMPTY_GUN_HELPER(automatic/smg/c20r) icon_state = "wt550" item_state = "arg" mag_type = /obj/item/ammo_box/magazine/wt550m9 - can_suppress = FALSE actions_types = list() - can_bayonet = TRUE - knife_x_offset = 25 - knife_y_offset = 12 show_magazine_on_sprite = TRUE show_magazine_on_sprite_ammo = TRUE empty_indicator = TRUE @@ -158,7 +149,6 @@ EMPTY_GUN_HELPER(automatic/smg/c20r) item_state = "m90" mag_type = /obj/item/ammo_box/magazine/m556 - can_suppress = FALSE gun_firenames = list(FIREMODE_SEMIAUTO = "single", FIREMODE_BURST = "burst fire", FIREMODE_FULLAUTO = "full auto", FIREMODE_OTHER = "underbarrel grenade launcher") gun_firemodes = list(FIREMODE_SEMIAUTO, FIREMODE_BURST, FIREMODE_OTHER) default_firemode = FIREMODE_SEMIAUTO @@ -241,7 +231,6 @@ EMPTY_GUN_HELPER(automatic/smg/c20r) icon_state = "firestorm" item_state = "firestorm" mag_type = /obj/item/ammo_box/magazine/c45_firestorm_mag - can_suppress = FALSE unique_mag_sprites_for_variants = TRUE burst_size = 1 actions_types = list() @@ -315,11 +304,9 @@ EMPTY_GUN_HELPER(automatic/smg/cm5) eject_empty_sound = 'sound/weapons/gun/rifle/skm_unload.ogg' weapon_weight = WEAPON_MEDIUM - w_class = WEIGHT_CLASS_BULKY + w_class = WEIGHT_CLASS_NORMAL mag_type = /obj/item/ammo_box/magazine/skm_545_39 - actions_types = list(/datum/action/item_action/fold_stock) //once again, ideally an attatchment in the future - recoil = 2 recoil_unwielded = 6 @@ -329,76 +316,35 @@ EMPTY_GUN_HELPER(automatic/smg/cm5) wield_delay = 0.6 SECONDS wield_slowdown = 0.35 - ///is the bipod deployed? - var/stock_folded = FALSE - - ///we add these two values to recoi/spread when we have the bipod deployed - var/stock_recoil_bonus = -2 - var/stock_spread_bonus = -5 - - var/folded_slowdown = 0.6 - var/folded_wield_delay = 0.6 SECONDS - - var/unfolded_slowdown = 0.35 - var/unfolded_wield_delay = 0.2 SECONDS - -/obj/item/gun/ballistic/automatic/smg/skm_carbine/ComponentInitialize() - . = ..() - AddElement(/datum/element/update_icon_updates_onmob) - -/datum/action/item_action/fold_stock - name = "Fold/Unfold stock" - desc = "Fold or unfold the stock for easier storage." - -/obj/item/gun/ballistic/automatic/smg/skm_carbine/ui_action_click(mob/user, action) - if(!istype(action, /datum/action/item_action/fold_stock)) - return ..() - fold(user) - - -/obj/item/gun/ballistic/automatic/smg/skm_carbine/proc/fold(mob/user) - if(stock_folded) - to_chat(user, "You unfold the stock on the [src].") - w_class = WEIGHT_CLASS_BULKY - wield_delay = folded_wield_delay - wield_slowdown = folded_slowdown - else - to_chat(user, "You fold the stock on the [src].") - w_class = WEIGHT_CLASS_NORMAL - wield_delay = unfolded_wield_delay - wield_slowdown = unfolded_slowdown - - if(wielded) - user.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/gun, multiplicative_slowdown = wield_slowdown) - - stock_folded = !stock_folded - playsound(src, 'sound/weapons/empty.ogg', 100, 1) - update_appearance() - - -/obj/item/gun/ballistic/automatic/smg/skm_carbine/calculate_recoil(mob/user, recoil_bonus = 0) - var/total_recoil = recoil_bonus - if(!stock_folded) - total_recoil += stock_recoil_bonus - - return ..(user, total_recoil) - -/obj/item/gun/ballistic/automatic/smg/skm_carbine/calculate_spread(mob/user, bonus_spread) - var/total_spread = bonus_spread - - if(!stock_folded) - total_spread += stock_spread_bonus - - return ..(user, total_spread) - -/obj/item/gun/ballistic/automatic/smg/skm_carbine/update_icon_state() - . = ..() - item_state = "[initial(item_state)][stock_folded ? "_nostock" : ""]" - mob_overlay_state = "[initial(item_state)][stock_folded ? "_nostock" : ""]" - -/obj/item/gun/ballistic/automatic/smg/skm_carbine/update_overlays() - . = ..() - . += "[base_icon_state || initial(icon_state)][stock_folded ? "_nostock" : "_stock"]" + valid_attachments = list( + /obj/item/attachment/silencer, + /obj/item/attachment/laser_sight, + /obj/item/attachment/rail_light, + /obj/item/attachment/bayonet, + /obj/item/attachment/foldable_stock + ) + + slot_available = list( + ATTACHMENT_SLOT_MUZZLE = 1, + ATTACHMENT_SLOT_RAIL = 1, + ATTACHMENT_SLOT_STOCK = 1 + ) + slot_offsets = list( + ATTACHMENT_SLOT_MUZZLE = list( + "x" = 26, + "y" = 20, + ), + ATTACHMENT_SLOT_RAIL = list( + "x" = 19, + "y" = 18, + ), + ATTACHMENT_SLOT_STOCK = list( + "x" = 11, + "y" = 20, + ) + ) + + default_attachments = list(/obj/item/attachment/foldable_stock) /obj/item/gun/ballistic/automatic/smg/skm_carbine/inteq name = "\improper SKM-44v Mongrel" @@ -426,16 +372,16 @@ EMPTY_GUN_HELPER(automatic/smg/cm5) recoil = 0 recoil_unwielded = 4 - stock_spread_bonus = -4 - stock_recoil_bonus = -1 - wield_delay = 0.4 SECONDS - folded_slowdown = 0.15 - folded_wield_delay = 0.2 SECONDS - - unfolded_slowdown = 0.35 - unfolded_wield_delay = 0.4 SECONDS + valid_attachments = list( + /obj/item/attachment/silencer, + /obj/item/attachment/laser_sight, + /obj/item/attachment/rail_light, + /obj/item/attachment/bayonet, + /obj/item/attachment/foldable_stock/inteq + ) + default_attachments = list(/obj/item/attachment/foldable_stock/inteq) /obj/item/gun/ballistic/automatic/smg/skm_carbine/inteq/proto name = "\improper Nanotrasen Saber SMG" @@ -447,4 +393,3 @@ EMPTY_GUN_HELPER(automatic/smg/cm5) bolt_type = BOLT_TYPE_LOCKING show_magazine_on_sprite = TRUE manufacturer = MANUFACTURER_NANOTRASEN_OLD - diff --git a/code/modules/projectiles/guns/ballistic/toy.dm b/code/modules/projectiles/guns/ballistic/toy.dm index 160569d3f86c..135a1b2d06b0 100644 --- a/code/modules/projectiles/guns/ballistic/toy.dm +++ b/code/modules/projectiles/guns/ballistic/toy.dm @@ -8,7 +8,6 @@ force = 0 throwforce = 0 burst_size = 3 - can_suppress = TRUE item_flags = NONE casing_ejector = FALSE manufacturer = MANUFACTURER_NANOTRASEN @@ -54,7 +53,6 @@ fire_sound = 'sound/items/syringeproj.ogg' item_flags = NONE casing_ejector = FALSE - can_suppress = FALSE pb_knockback = 0 recoil = -10 //its a toy... recoil_unwielded = -10 @@ -85,7 +83,6 @@ /obj/item/gun/ballistic/automatic/smg/c20r/toy name = "donksoft SMG" desc = "A bullpup two-round burst toy SMG, designated 'C-20r'. Ages 8 and up." - can_suppress = FALSE item_flags = NONE mag_type = /obj/item/ammo_box/magazine/toy/smgm45 fire_sound = 'sound/items/syringeproj.ogg' @@ -105,7 +102,6 @@ name = "donksoft LMG" desc = "A heavily modified toy light machine gun, designated 'L6 SAW'. Ages 8 and up." fire_sound = 'sound/items/syringeproj.ogg' - can_suppress = FALSE item_flags = NONE mag_type = /obj/item/ammo_box/magazine/toy/m762 casing_ejector = FALSE diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 07eb9a159897..abe3e3fd7b43 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -10,41 +10,31 @@ has_safety = TRUE safety = TRUE + modifystate = FALSE + ammo_x_offset = 2 + gun_firemodes = list(FIREMODE_SEMIAUTO) default_firemode = FIREMODE_SEMIAUTO fire_select_icon_state_prefix = "laser_" - var/obj/item/stock_parts/cell/gun/cell //What type of power cell this uses - var/cell_type = /obj/item/stock_parts/cell/gun - var/modifystate = 0 - var/list/ammo_type = list(/obj/item/ammo_casing/energy) - var/select = 1 //The state of the select fire switch. Determines from the ammo_type list what kind of shot is fired next. - var/can_charge = TRUE //Can it be charged in a recharger? - var/automatic_charge_overlays = TRUE //Do we handle overlays with base update_appearance()? - var/charge_sections = 4 - ammo_x_offset = 2 - var/shaded_charge = FALSE //if this gun uses a stateful charge bar for more detail - var/selfcharge = 0 - var/charge_tick = 0 - var/charge_delay = 4 - var/use_cyborg_cell = FALSE //whether the gun's cell drains the cyborg user's cell to recharge - var/dead_cell = FALSE //set to true so the gun is given an empty cell - - var/internal_cell = FALSE ///if the gun's cell cannot be replaced - var/small_gun = FALSE ///if the gun is small and can only fit the small gun cell - var/big_gun = FALSE ///if the gun is big and can fit the comically large gun cell - var/unscrewing_time = 20 ///Time it takes to unscrew the cell - - ///Whether the gun can be tacloaded by slapping a fresh magazine directly on it - var/tac_reloads = FALSE - ///If we allow tacitcal reloads, how long should it take to reload? - var/tactical_reload_delay = 1.2 SECONDS - - var/load_sound = 'sound/weapons/gun/general/magazine_insert_full.ogg' //Sound when inserting magazine. UPDATE PLEASE - var/eject_sound = 'sound/weapons/gun/general/magazine_remove_full.ogg' //Sound of ejecting a cell. UPDATE PLEASE - var/sound_volume = 40 //Volume of loading/unloading sounds - var/load_sound_vary = TRUE //Should the load/unload sounds vary? + tac_reloads = FALSE + tactical_reload_delay = 1.2 SECONDS + + valid_attachments = list( + /obj/item/attachment/laser_sight, + /obj/item/attachment/rail_light, + /obj/item/attachment/bayonet + ) + slot_available = list( + ATTACHMENT_SLOT_RAIL = 1 + ) + slot_offsets = list( + ATTACHMENT_SLOT_RAIL = list( + "x" = 19, + "y" = 18, + ) + ) /obj/item/gun/energy/emp_act(severity) . = ..() @@ -63,8 +53,8 @@ cell = new cell_type(src) else cell = new(src) - if(!dead_cell) - cell.give(cell.maxcharge) + if(dead_cell) + cell.use(cell.maxcharge) update_ammo_types() recharge_newshot(TRUE) if(selfcharge) @@ -133,16 +123,16 @@ return ..() /obj/item/gun/energy/proc/insert_cell(mob/user, obj/item/stock_parts/cell/gun/C) - if(small_gun && !istype(C, /obj/item/stock_parts/cell/gun/mini)) + if(mag_size == MAG_SIZE_SMALL && !istype(C, /obj/item/stock_parts/cell/gun/mini)) to_chat(user, span_warning("\The [C] doesn't seem to fit into \the [src]...")) return FALSE - if(!big_gun && istype(C, /obj/item/stock_parts/cell/gun/large)) + if(mag_size == MAG_SIZE_LARGE && !istype(C, /obj/item/stock_parts/cell/gun/large)) to_chat(user, span_warning("\The [C] doesn't seem to fit into \the [src]...")) return FALSE if(user.transferItemToLoc(C, src)) cell = C to_chat(user, span_notice("You load the [C] into \the [src].")) - playsound(src, load_sound, sound_volume, load_sound_vary) + playsound(src, load_sound, load_sound_volume, load_sound_vary) update_appearance() return TRUE else @@ -150,7 +140,7 @@ return FALSE /obj/item/gun/energy/proc/eject_cell(mob/user, obj/item/stock_parts/cell/gun/tac_load = null) - playsound(src, load_sound, sound_volume, load_sound_vary) + playsound(src, load_sound, load_sound_volume, load_sound_vary) cell.forceMove(drop_location()) var/obj/item/stock_parts/cell/gun/old_cell = cell old_cell.update_appearance() @@ -170,17 +160,13 @@ user.put_in_hands(old_cell) update_appearance() -/obj/item/gun/energy/get_gun_attachments() +/obj/item/gun/energy/screwdriver_act(mob/living/user, obj/item/I) if(cell && !internal_cell) - attachment_options += list("Cell" = image(icon = cell.icon, icon_state = cell.icon_state)) - ..() - -/obj/item/gun/energy/remove_gun_attachments(mob/living/user, obj/item/I, picked_option) - if(picked_option == "Cell") - if(I.use_tool(src, user, unscrewing_time, volume=100)) - eject_cell(user, I) - return TRUE - ..() + to_chat(user, span_notice("You begin unscrewing and pulling out the cell...")) + if(I.use_tool(src, user, unscrewing_time, volume = 100)) + to_chat(user, span_notice("You remove the power cell.")) + eject_cell(user) + return ..() /obj/item/gun/energy/can_shoot(visuals) if(safety && !visuals) diff --git a/code/modules/projectiles/guns/energy/energy_gun.dm b/code/modules/projectiles/guns/energy/energy_gun.dm index 6988f1f6cb72..90bfa9a8ead1 100644 --- a/code/modules/projectiles/guns/energy/energy_gun.dm +++ b/code/modules/projectiles/guns/energy/energy_gun.dm @@ -8,11 +8,8 @@ icon_state = "energy" item_state = null //so the human update icon uses the icon_state instead. ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser) - modifystate = 1 - can_flashlight = TRUE + modifystate = TRUE ammo_x_offset = 2 - flight_x_offset = 15 - flight_y_offset = 10 dual_wield_spread = 60 manufacturer = MANUFACTURER_SHARPLITE_NEW @@ -26,25 +23,16 @@ item_state = "gun" w_class = WEIGHT_CLASS_SMALL cell_type = /obj/item/stock_parts/cell/gun/mini - small_gun = TRUE + mag_size = MAG_SIZE_SMALL throwforce = 11 //This is funny, trust me. ammo_x_offset = 2 charge_sections = 3 - can_flashlight = FALSE // Can't attach or detach the flashlight, and override it's icon update - gunlight_state = "mini-light" - flight_x_offset = 19 - flight_y_offset = 13 - wield_delay = 0.2 SECONDS wield_slowdown = 0.15 spread = 2 spread_unwielded = 5 -/obj/item/gun/energy/e_gun/mini/Initialize() - set_gun_light(new /obj/item/flashlight/seclite(src)) - return ..() - /obj/item/gun/energy/e_gun/mini/empty_cell dead_cell = TRUE @@ -108,10 +96,9 @@ desc = "The \"Dynamic Rapid-Apprehension of the Guilty\" net is a revolution in law enforcement technology." icon_state = "dragnet" item_state = "dragnet" - lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + lefthand_file = GUN_LEFTHAND_ICON + righthand_file = GUN_RIGHTHAND_ICON ammo_type = list(/obj/item/ammo_casing/energy/net, /obj/item/ammo_casing/energy/trap) - can_flashlight = FALSE ammo_x_offset = 1 /obj/item/gun/energy/e_gun/dragnet/snare @@ -128,7 +115,6 @@ w_class = WEIGHT_CLASS_HUGE ammo_type = list(/obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/laser) weapon_weight = WEAPON_HEAVY - can_flashlight = FALSE trigger_guard = TRIGGER_GUARD_NONE ammo_x_offset = 2 @@ -198,7 +184,7 @@ item_state = "gun" ammo_x_offset = 2 charge_sections = 6 - small_gun = TRUE + mag_size = MAG_SIZE_SMALL wield_delay = 0.2 SECONDS wield_slowdown = 0.15 @@ -242,7 +228,7 @@ inhand_y_dimension = 64 icon_state = "iotshotgun" item_state = "shotgun_combat" - shaded_charge = 1 + shaded_charge = TRUE w_class = WEIGHT_CLASS_BULKY ammo_type = list(/obj/item/ammo_casing/energy/disabler/scatter/ultima, /obj/item/ammo_casing/energy/laser/ultima) var/obj/item/modular_computer/integratedNTOS @@ -257,10 +243,7 @@ mob_overlay_icon = 'icons/obj/guns/manufacturer/eoehoma/onmob.dmi' icon_state = "e11" ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser/eoehoma) - can_flashlight = TRUE ammo_x_offset = 0 - flight_x_offset = 20 - flight_y_offset = 9 spread = 80 spread_unwielded = 140 dual_wield_spread = 140 diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index ac3aa9e3d21a..2ca71649a6f7 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -8,14 +8,8 @@ item_flags = NONE obj_flags = UNIQUE_RENAME weapon_weight = WEAPON_LIGHT - can_flashlight = TRUE - flight_x_offset = 15 - flight_y_offset = 9 automatic_charge_overlays = FALSE - can_bayonet = TRUE - knife_x_offset = 20 - knife_y_offset = 12 - internal_cell = TRUE + internal_cell = TRUE //prevents you from giving it an OP cell - WS Edit custom_price = 750 w_class = WEIGHT_CLASS_BULKY @@ -28,12 +22,18 @@ var/overheat = FALSE var/mob/holder - var/max_mod_capacity = 100 var/list/modkits = list() var/recharge_timerid + slot_offsets = list( + ATTACHMENT_SLOT_RAIL = list( + "x" = 24, + "y" = 13, + ) + ) + /obj/item/gun/energy/kinetic_accelerator/shoot_with_empty_chamber(mob/living/user) playsound(src, dry_fire_sound, 30, TRUE) //click sound but no to_chat message to cut on spam return diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index c564ae32b4da..eff3d67b2df1 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -84,7 +84,7 @@ icon_state = "cshotgun" item_state = "shotgun" desc = "A combat shotgun gutted and refitted with an internal laser system. Can switch between taser and scattered disabler shots." - shaded_charge = 0 + shaded_charge = FALSE ammo_type = list(/obj/item/ammo_casing/energy/disabler/scatter, /obj/item/ammo_casing/energy/electrode) manufacturer = MANUFACTURER_NONE @@ -96,7 +96,7 @@ icon_state = "lasercannon" item_state = "laser" w_class = WEIGHT_CLASS_BULKY - big_gun = TRUE + mag_size = MAG_SIZE_LARGE cell_type = "/obj/item/stock_parts/cell/gun/large" force = 10 flags_1 = CONDUCT_1 @@ -203,7 +203,7 @@ item_state = "gun" ammo_x_offset = 2 charge_sections = 4 - small_gun = TRUE + mag_size = MAG_SIZE_SMALL w_class = WEIGHT_CLASS_NORMAL cell_type = /obj/item/stock_parts/cell/gun/mini ammo_type = list(/obj/item/ammo_casing/energy/lasergun/hitscan) @@ -245,7 +245,7 @@ icon_state = "e50" item_state = "e50" - big_gun = TRUE + mag_size = MAG_SIZE_LARGE cell_type = /obj/item/stock_parts/cell/gun/large ammo_type = list(/obj/item/ammo_casing/energy/laser/eoehoma/e50) weapon_weight = WEAPON_HEAVY diff --git a/code/modules/projectiles/guns/energy/mounted.dm b/code/modules/projectiles/guns/energy/mounted.dm index 4dc5cae77558..cf67db9fd5ae 100644 --- a/code/modules/projectiles/guns/energy/mounted.dm +++ b/code/modules/projectiles/guns/energy/mounted.dm @@ -6,7 +6,6 @@ item_state = "armcannonstun4" force = 5 selfcharge = 1 - can_flashlight = FALSE trigger_guard = TRIGGER_GUARD_ALLOW_ALL // Has no trigger at all, uses neural signals instead /obj/item/gun/energy/e_gun/advtaser/mounted/dropped()//if somebody manages to drop this somehow... diff --git a/code/modules/projectiles/guns/energy/pulse.dm b/code/modules/projectiles/guns/energy/pulse.dm index dfa23e26b468..c2e5b4cb2933 100644 --- a/code/modules/projectiles/guns/energy/pulse.dm +++ b/code/modules/projectiles/guns/energy/pulse.dm @@ -39,11 +39,8 @@ icon_state = "pulse_carbine" item_state = null internal_cell = FALSE - big_gun = TRUE //haha gun go brr + mag_size = MAG_SIZE_LARGE //haha gun go brr cell_type = /obj/item/stock_parts/cell/gun/large - can_flashlight = TRUE - flight_x_offset = 18 - flight_y_offset = 12 ammo_x_offset = 2 charge_sections = 4 diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 07f0aebaa9a0..09de7690b5ea 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -6,9 +6,8 @@ shaded_charge = FALSE ammo_x_offset = 2 ammo_y_offset = 2 - can_flashlight = FALSE w_class = WEIGHT_CLASS_HUGE - big_gun = TRUE //yes, you can put the comically large cell in it. No, you aren't getting it roundstart. You slut. + mag_size = MAG_SIZE_LARGE //yes, you can put the comically large cell in it. No, you aren't getting it roundstart. You slut. flags_1 = CONDUCT_1 slot_flags = ITEM_SLOT_BACK ammo_type = list(/obj/item/ammo_casing/energy/ion) @@ -28,9 +27,6 @@ slot_flags = ITEM_SLOT_BELT ammo_x_offset = 2 ammo_y_offset = 0 - can_flashlight = TRUE - flight_x_offset = 18 - flight_y_offset = 11 /obj/item/gun/energy/decloner name = "biological demolecularisor" @@ -51,10 +47,10 @@ icon_state = "flora" item_state = "gun" ammo_type = list(/obj/item/ammo_casing/energy/flora/yield, /obj/item/ammo_casing/energy/flora/mut, /obj/item/ammo_casing/energy/flora/revolution) - modifystate = 1 + modifystate = TRUE ammo_x_offset = 1 selfcharge = 1 - shaded_charge = 1 + shaded_charge = TRUE /obj/item/gun/energy/meteorgun name = "meteor gun" @@ -98,7 +94,6 @@ overheat_time = 20 holds_charge = TRUE unique_frequency = TRUE - can_flashlight = FALSE max_mod_capacity = 0 manufacturer = MANUFACTURER_SCARBOROUGH @@ -108,7 +103,7 @@ icon_state = "crossbowlarge" w_class = WEIGHT_CLASS_NORMAL custom_materials = list(/datum/material/iron=4000) - suppressed = null + suppressed = FALSE ammo_type = list(/obj/item/ammo_casing/energy/bolt/large) manufacturer = MANUFACTURER_NONE diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index 168bbdc099dc..e70c46cc76f6 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -5,7 +5,6 @@ item_state = null //so the human update icon uses the icon_state instead. ammo_type = list(/obj/item/ammo_casing/energy/electrode) ammo_x_offset = 3 - spread = 2 spread_unwielded = 4 @@ -22,7 +21,6 @@ /obj/item/gun/energy/e_gun/advtaser/cyborg name = "cyborg taser" desc = "An integrated hybrid taser that draws directly from a cyborg's power cell. The weapon contains a limiter to prevent the cyborg's power cell from overheating." - can_flashlight = FALSE can_charge = FALSE use_cyborg_cell = TRUE @@ -37,11 +35,7 @@ item_state = null ammo_type = list(/obj/item/ammo_casing/energy/disabler) ammo_x_offset = 2 - can_flashlight = TRUE - flight_x_offset = 15 - flight_y_offset = 10 manufacturer = MANUFACTURER_SHARPLITE_NEW - spread = 2 spread_unwielded = 4 diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm index 8b6626bc5e97..b131b03ec148 100644 --- a/code/modules/projectiles/guns/misc/beam_rifle.dm +++ b/code/modules/projectiles/guns/misc/beam_rifle.dm @@ -29,7 +29,7 @@ w_class = WEIGHT_CLASS_BULKY ammo_type = list(/obj/item/ammo_casing/energy/beam_rifle/hitscan) internal_cell = FALSE //prevents you from giving it an OP cell - WS Edit //shut up dumb nerd - big_gun = TRUE + mag_size = MAG_SIZE_LARGE cell_type = "/obj/item/stock_parts/cell/gun/large" canMouseDown = TRUE var/aiming = FALSE diff --git a/code/modules/projectiles/guns/misc/syringe_gun.dm b/code/modules/projectiles/guns/misc/syringe_gun.dm index 84d00b226371..809c15682cd4 100644 --- a/code/modules/projectiles/guns/misc/syringe_gun.dm +++ b/code/modules/projectiles/guns/misc/syringe_gun.dm @@ -80,7 +80,6 @@ w_class = WEIGHT_CLASS_SMALL force = 2 //Also very weak because it's smaller suppressed = TRUE //Softer fire sound - can_unsuppress = FALSE //Permanently silenced /obj/item/gun/syringe/dna name = "modified syringe gun" diff --git a/code/modules/projectiles/guns/powered.dm b/code/modules/projectiles/guns/powered.dm index ac7418748d9b..a9ab2f6365f4 100644 --- a/code/modules/projectiles/guns/powered.dm +++ b/code/modules/projectiles/guns/powered.dm @@ -1,21 +1,6 @@ /obj/item/gun/ballistic/automatic/powered mag_type = /obj/item/ammo_box/magazine/gauss - can_suppress = FALSE - - var/obj/item/stock_parts/cell/cell - var/cell_type = /obj/item/stock_parts/cell/gun - var/charge_sections = 3 - var/empty_battery_sound = FALSE // play empty alarm if no battery - - var/shaded_charge = FALSE //if this gun uses a stateful charge bar for more detail - var/automatic_charge_overlays = TRUE //Do we handle overlays with base update_appearance()? - - var/internal_cell = FALSE ///if the gun's cell cannot be replaced - var/small_gun = FALSE ///if the gun is small and can only fit the small gun cell - var/big_gun = FALSE ///if the gun is big and can fit the comically large gun cell - var/unscrewing_time = 2 SECONDS ///Time it takes to unscrew the cell - var/sound_volume = 40 //Volume of loading/unloading cell sounds - + charge_sections = 3 /obj/item/gun/ballistic/automatic/powered/Initialize() . = ..() @@ -61,24 +46,24 @@ return ..() /obj/item/gun/ballistic/automatic/powered/proc/insert_cell(mob/user, obj/item/stock_parts/cell/gun/C) - if(small_gun && !istype(C, /obj/item/stock_parts/cell/gun/mini)) - to_chat(user, "[C] doesn't seem to fit into [src]...") + if(mag_size == MAG_SIZE_SMALL && !istype(C, /obj/item/stock_parts/cell/gun/mini)) + to_chat(user, "\The [C] doesn't seem to fit into \the [src]...") return FALSE - if(!big_gun && istype(C, /obj/item/stock_parts/cell/gun/large)) - to_chat(user, "[C] doesn't seem to fit into [src]...") + if(mag_size == MAG_SIZE_LARGE && !istype(C, /obj/item/stock_parts/cell/gun/large)) + to_chat(user, "\The [C] doesn't seem to fit into \the [src]...") return FALSE if(user.transferItemToLoc(C, src)) cell = C - to_chat(user, "You load [C] into [src].") - playsound(src, load_sound, sound_volume, load_sound_vary) + to_chat(user, "You load the [C] into \the [src].") + playsound(src, load_sound, load_sound_volume, load_sound_vary) update_appearance() return TRUE else - to_chat(user, "You cannot seem to get [src] out of your hands!") + to_chat(user, "You cannot seem to get \the [src] out of your hands!") return FALSE /obj/item/gun/ballistic/automatic/powered/proc/eject_cell(mob/user, obj/item/stock_parts/cell/gun/tac_load = null) - playsound(src, load_sound, sound_volume, load_sound_vary) + playsound(src, load_sound, load_sound_volume, load_sound_vary) cell.forceMove(drop_location()) var/obj/item/stock_parts/cell/gun/old_cell = cell cell = null @@ -88,7 +73,7 @@ update_appearance() /obj/item/gun/ballistic/automatic/powered/screwdriver_act(mob/living/user, obj/item/I) - if(cell && !internal_cell && !bayonet && (!gun_light || !can_flashlight)) + if(cell && !internal_cell) to_chat(user, "You begin unscrewing and pulling out the cell...") if(I.use_tool(src, user, unscrewing_time, volume=100)) to_chat(user, "You remove the power cell.") diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 11cbd03c9787..78326279b6f9 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -395,7 +395,7 @@ to_chat(user, "You remove [vial] from [src].") vial = null update_appearance() - playsound(loc, 'sound/weapons/empty.ogg', 50, 1) + playsound(loc, SOUND_EMPTY_MAG, 50, 1) else to_chat(user, "This hypo isn't loaded!") return diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 05f68682083c..b4f46e6e4c19 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -260,8 +260,8 @@ icon = 'icons/obj/guns/projectile.dmi' icon_state = "chemsprayer" item_state = "chemsprayer" - lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + lefthand_file = GUN_LEFTHAND_ICON + righthand_file = GUN_RIGHTHAND_ICON throwforce = 0 w_class = WEIGHT_CLASS_NORMAL stream_mode = 1 @@ -298,8 +298,8 @@ desc = "A utility used to spray large amounts of cleaning reagents in a given area. It regenerates space cleaner by itself but it's unable to be fueled by normal means." icon_state = "chemsprayer_janitor" item_state = "chemsprayer_janitor" - lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + lefthand_file = GUN_LEFTHAND_ICON + righthand_file = GUN_RIGHTHAND_ICON reagent_flags = NONE list_reagents = list(/datum/reagent/space_cleaner = 1000) volume = 1000 diff --git a/code/modules/research/designs/mining_designs.dm b/code/modules/research/designs/mining_designs.dm index 2cddc5043c3f..aa221c2b21a7 100644 --- a/code/modules/research/designs/mining_designs.dm +++ b/code/modules/research/designs/mining_designs.dm @@ -8,7 +8,7 @@ id = "cargoexpress"//the coder reading this build_type = IMPRINTER materials = list(/datum/material/glass = 1000) - build_path = /obj/item/circuitboard/computer/cargo/express + build_path = /obj/item/circuitboard/computer/cargo category = list("Mining Designs") departmental_flags = DEPARTMENTAL_FLAG_CARGO diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm index 3353dcfb3289..c444336adde5 100644 --- a/code/modules/research/designs/weapon_designs.dm +++ b/code/modules/research/designs/weapon_designs.dm @@ -558,7 +558,7 @@ id = "suppressor" build_type = PROTOLATHE materials = list(/datum/material/iron = 2000, /datum/material/silver = 500) - build_path = /obj/item/suppressor + build_path = /obj/item/attachment/silencer category = list("Weapons") departmental_flags = DEPARTMENTAL_FLAG_SECURITY diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index 11eb6a4b49e6..9e935611e15f 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -683,7 +683,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) /datum/uplink_item/stealthy_weapons/suppressor name = "Suppressor" desc = "This suppressor will silence the shots of the weapon it is attached to for increased stealth and superior ambushing capability. It is compatible with many small ballistic guns including the Stechkin and C-20r, but not revolvers or energy guns." - item = /obj/item/suppressor + item = /obj/item/attachment/silencer cost = 3 surplus = 10 exclude_modes = list(/datum/game_mode/nuclear/clown_ops) diff --git a/html/changelogs/archive/2024-07.yml b/html/changelogs/archive/2024-07.yml index d16159c1679a..7b33a0249022 100644 --- a/html/changelogs/archive/2024-07.yml +++ b/html/changelogs/archive/2024-07.yml @@ -92,3 +92,34 @@ - balance: Decreased the amount of landmines required for its mission and increased the value per mine slightly - rscdel: Capsaicin no longer Boils you +2024-07-15: + FalloutFalcon: + - refactor: refactored attachments to be modular + Sadhorizon: + - tweak: Changed sunskipper's prefix to SV. + - bugfix: Added a missing pipe to the sunskipper. + Skies-Of-Blue: + - rscadd: typing indicators now trigger off of the command bar + - rscadd: an SSD Indicator for when you have been disconnected for less than three + minutes + - balance: players will now remain awake for three minutes after disconnecting, + with a new SSD icon to boot! + - balance: players SSD longer than three minutes will lose their icon and fall asleep, + much like the previous behavior + SomeguyManperson: + - bugfix: gun cargo packs now act more as they would be expected to +2024-07-17: + FalloutFalcon: + - rscadd: Orbit menu is less cluttered and just shows the real name, hovering over + it shows their standard name. + - refactor: refactored express console to not be a subtype of the cargo console + and replacing it. + Martinpachu: + - balance: Doubled the price on every automatic gun and added 250 credits to the + price of every semi-auto pistol. + Sadhorizon: + - tweak: Choice beacons were reflavored into choice boxes. + - rscdel: Removed a bunch of meme, weird and unused items from the loadout. + - tweak: Reflavored the Cybersun labcoat into a generic "translucent labcoat" + SomeguyManperson: + - bugfix: ships docked to eachother now share gravity diff --git a/html/typing_indicator.html b/html/typing_indicator.html new file mode 100644 index 000000000000..2988edff55fa --- /dev/null +++ b/html/typing_indicator.html @@ -0,0 +1,46 @@ + + + + + + + + + diff --git a/icons/mob/ssd_indicator.dmi b/icons/mob/ssd_indicator.dmi new file mode 100644 index 000000000000..3f7d100b6c67 Binary files /dev/null and b/icons/mob/ssd_indicator.dmi differ diff --git a/icons/obj/guns/48x32guns.dmi b/icons/obj/guns/48x32guns.dmi index cbc495275add..960b9ec448af 100644 Binary files a/icons/obj/guns/48x32guns.dmi and b/icons/obj/guns/48x32guns.dmi differ diff --git a/icons/obj/guns/attachments.dmi b/icons/obj/guns/attachments.dmi new file mode 100644 index 000000000000..29ae084d5759 Binary files /dev/null and b/icons/obj/guns/attachments.dmi differ diff --git a/icons/obj/guns/bayonets.dmi b/icons/obj/guns/bayonets.dmi deleted file mode 100644 index 32b5448b8edc..000000000000 Binary files a/icons/obj/guns/bayonets.dmi and /dev/null differ diff --git a/icons/obj/guns/energy.dmi b/icons/obj/guns/energy.dmi index e02a7e288cc8..6a32de5b08fb 100644 Binary files a/icons/obj/guns/energy.dmi and b/icons/obj/guns/energy.dmi differ diff --git a/icons/obj/guns/flashlights.dmi b/icons/obj/guns/flashlights.dmi deleted file mode 100644 index eef6d953f94a..000000000000 Binary files a/icons/obj/guns/flashlights.dmi and /dev/null differ diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi index 986c2f99692f..ab051d8a21bb 100644 Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.dmi differ diff --git a/interface/skin.dmf b/interface/skin.dmf index 9d933e057c46..18122c5e3e89 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -90,6 +90,15 @@ window "mainwindow" background-color = #272727 is-visible = false saved-params = "" + elem "commandbar_spy" + type = BROWSER + is-default = false + pos = 0,0 + size = 200x200 + anchor1 = -1,-1 + anchor2 = -1,-1 + is-visible = false + saved-params = "" window "mapwindow" elem "mapwindow" diff --git a/shiptest.dme b/shiptest.dme index 4aca805d1589..5eb7b99be531 100644 --- a/shiptest.dme +++ b/shiptest.dme @@ -468,6 +468,8 @@ #include "code\datums\components\anti_magic.dm" #include "code\datums\components\armor_plate.dm" #include "code\datums\components\art.dm" +#include "code\datums\components\attachment.dm" +#include "code\datums\components\attachment_holder.dm" #include "code\datums\components\bandage.dm" #include "code\datums\components\bane.dm" #include "code\datums\components\beetlejuice.dm" @@ -1212,6 +1214,12 @@ #include "code\game\objects\items\vending_items.dm" #include "code\game\objects\items\wayfinding.dm" #include "code\game\objects\items\weaponry.dm" +#include "code\game\objects\items\attachments\_attachment.dm" +#include "code\game\objects\items\attachments\bayonet.dm" +#include "code\game\objects\items\attachments\laser_sight.dm" +#include "code\game\objects\items\attachments\rail_light.dm" +#include "code\game\objects\items\attachments\silencer.dm" +#include "code\game\objects\items\attachments\stock.dm" #include "code\game\objects\items\circuitboards\circuitboard.dm" #include "code\game\objects\items\circuitboards\computer_circuitboards.dm" #include "code\game\objects\items\circuitboards\machine_circuitboards.dm" @@ -1886,9 +1894,9 @@ #include "code\modules\cargo\bounty.dm" #include "code\modules\cargo\bounty_console.dm" #include "code\modules\cargo\centcom_podlauncher.dm" +#include "code\modules\cargo\console.dm" #include "code\modules\cargo\export_scanner.dm" #include "code\modules\cargo\exports.dm" -#include "code\modules\cargo\expressconsole.dm" #include "code\modules\cargo\gondolapod.dm" #include "code\modules\cargo\order.dm" #include "code\modules\cargo\packs.dm" @@ -1968,6 +1976,7 @@ #include "code\modules\client\verbs\ooc.dm" #include "code\modules\client\verbs\ping.dm" #include "code\modules\client\verbs\reset_held_keys.dm" +#include "code\modules\client\verbs\typing.dm" #include "code\modules\client\verbs\who.dm" #include "code\modules\clothing\chameleon.dm" #include "code\modules\clothing\clothing.dm" diff --git a/tgui/packages/tgui/interfaces/Cargo.js b/tgui/packages/tgui/interfaces/Cargo.js deleted file mode 100644 index 9dfcd417f593..000000000000 --- a/tgui/packages/tgui/interfaces/Cargo.js +++ /dev/null @@ -1,533 +0,0 @@ -import { flow } from 'common/fp'; -import { filter, sortBy } from 'common/collections'; -import { useBackend, useSharedState } from '../backend'; -import { - AnimatedNumber, - Box, - Button, - Flex, - Icon, - Input, - LabeledList, - NoticeBox, - Section, - Stack, - Table, - Tabs, -} from '../components'; -import { formatMoney } from '../format'; -import { Window } from '../layouts'; - -export const Cargo = (props, context) => { - return ( - - - - - - ); -}; - -export const CargoContent = (props, context) => { - const { act, data } = useBackend(context); - const [tab, setTab] = useSharedState(context, 'tab', 'catalog'); - const { requestonly } = data; - const cart = data.cart || []; - const requests = data.requests || []; - return ( - - -
- - setTab('catalog')} - > - Catalog - - 0 && 'yellow'} - selected={tab === 'requests'} - onClick={() => setTab('requests')} - > - Requests ({requests.length}) - - {!requestonly && ( - <> - 0 && 'yellow'} - selected={tab === 'cart'} - onClick={() => setTab('cart')} - > - Checkout ({cart.length}) - - setTab('help')} - > - Help - - - )} - -
- {tab === 'catalog' && } - {tab === 'requests' && } - {tab === 'cart' && } - {tab === 'help' && } -
- ); -}; - -const CargoStatus = (props, context) => { - const { act, data } = useBackend(context); - const { - department, - grocery, - away, - docked, - loan, - loan_dispatched, - location, - message, - points, - requestonly, - can_send, - } = data; - return ( -
- formatMoney(value)} - /> - {' credits'} - - } - > - - - {(docked && !requestonly && can_send && ( -
- ); -}; - -/** - * Take entire supplies tree - * and return a flat supply pack list that matches search, - * sorted by name and only the first page. - * @param {any[]} supplies Supplies list. - * @param {string} search The search term - * @returns {any[]} The flat list of supply packs. - */ -const searchForSupplies = (supplies, search) => { - search = search.toLowerCase(); - - return flow([ - (categories) => categories.flatMap((category) => category.packs), - filter( - (pack) => - pack.name?.toLowerCase().includes(search.toLowerCase()) || - pack.desc?.toLowerCase().includes(search.toLowerCase()) - ), - sortBy((pack) => pack.name), - (packs) => packs.slice(0, 25), - ])(supplies); -}; - -export const CargoCatalog = (props, context) => { - const { express } = props; - const { act, data } = useBackend(context); - - const { self_paid, app_cost } = data; - - const supplies = Object.values(data.supplies); - - const [activeSupplyName, setActiveSupplyName] = useSharedState( - context, - 'supply', - supplies[0]?.name - ); - - const [searchText, setSearchText] = useSharedState( - context, - 'search_text', - '' - ); - - const activeSupply = - activeSupplyName === 'search_results' - ? { packs: searchForSupplies(supplies, searchText) } - : supplies.find((supply) => supply.name === activeSupplyName); - - return ( -
- - act('toggleprivate')} - /> - - ) - } - > - - - - - - - - - - { - if (value === searchText) { - return; - } - - if (value.length) { - // Start showing results - setActiveSupplyName('search_results'); - } else if (activeSupplyName === 'search_results') { - // return to normal category - setActiveSupplyName(supplies[0]?.name); - } - setSearchText(value); - }} - onChange={(e, value) => { - // Allow edge cases like the X button to work - const onInput = e.target?.props?.onInput; - if (onInput) { - onInput(e, value); - } - }} - /> - - - - {supplies.map((supply) => ( - { - setActiveSupplyName(supply.name); - setSearchText(''); - }} - > - {supply.name} ({supply.packs.length}) - - ))} - - - - - {activeSupply?.packs.map((pack) => { - const tags = []; - if (pack.small_item) { - tags.push('Small'); - } - if (pack.access) { - tags.push('Restricted'); - } - return ( - - {pack.name} - - {tags.join(', ')} - - - - - - ); - })} -
-
-
-
- ); -}; - -const CargoRequests = (props, context) => { - const { act, data } = useBackend(context); - const { requestonly, can_send, can_approve_requests } = data; - const requests = data.requests || []; - // Labeled list reimplementation to squeeze extra columns out of it - return ( -
act('denyall')} - /> - ) - } - > - {requests.length === 0 && No Requests} - {requests.length > 0 && ( - - {requests.map((request) => ( - - - #{request.id} - - {request.object} - - {request.orderer} - - - {request.reason} - - - {formatMoney(request.cost)} cr - - {(!requestonly || can_send) && can_approve_requests && ( - -
- )} -
- ); -}; - -const CargoCartButtons = (props, context) => { - const { act, data } = useBackend(context); - const { requestonly, can_send, can_approve_requests } = data; - const cart = data.cart || []; - const total = cart.reduce((total, entry) => total + entry.cost, 0); - if (requestonly || !can_send || !can_approve_requests) { - return null; - } - return ( - <> - - {cart.length === 0 && 'Cart is empty'} - {cart.length === 1 && '1 item'} - {cart.length >= 2 && cart.length + ' items'}{' '} - {total > 0 && `(${formatMoney(total)} cr)`} - -