diff --git a/_maps/map_files/RandomRuins/SpaceRuins/onehalf.dmm b/_maps/map_files/RandomRuins/SpaceRuins/onehalf.dmm index 9cca10a3239..da0e0f1d570 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/onehalf.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/onehalf.dmm @@ -259,7 +259,6 @@ /area/ruin/space/onehalf/hallway) "aM" = ( /obj/structure/disposalpipe/segment, -/obj/structure/disposalpipe/segment, /obj/machinery/door/poddoor{ id_tag = "bayint1"; name = "mining drone bay blast door" @@ -636,9 +635,6 @@ /area/ruin/space/onehalf/hallway) "bA" = ( /obj/structure/disposalpipe/segment, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/structure/disposalpipe/segment{ dir = 4 }, @@ -653,15 +649,6 @@ }, /turf/simulated/floor/plasteel, /area/ruin/space/onehalf/drone_bay) -"bC" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/simulated/floor/plasteel, -/area/ruin/space/onehalf/drone_bay) "bD" = ( /obj/structure/disposalpipe/junction{ dir = 8 @@ -1643,7 +1630,7 @@ aD aq aX bm -bC +bn bT aa cn diff --git a/_maps/map_files/stations/boxstation.dmm b/_maps/map_files/stations/boxstation.dmm index 57c028ebbfc..31bfcbabf97 100644 --- a/_maps/map_files/stations/boxstation.dmm +++ b/_maps/map_files/stations/boxstation.dmm @@ -52972,7 +52972,6 @@ icon_state = "1-2" }, /obj/structure/disposalpipe/segment, -/obj/structure/disposalpipe/segment, /obj/structure/sign/securearea{ pixel_x = -32 }, @@ -74887,7 +74886,6 @@ /area/station/maintenance/apmaint) "owP" = ( /obj/structure/disposalpipe/segment, -/obj/structure/disposalpipe/segment, /turf/simulated/floor/plating/airless, /area/station/maintenance/asmaint) "oxe" = ( diff --git a/_maps/map_files/stations/cerestation.dmm b/_maps/map_files/stations/cerestation.dmm index ccc69336a86..31aa308fa5a 100644 --- a/_maps/map_files/stations/cerestation.dmm +++ b/_maps/map_files/stations/cerestation.dmm @@ -1839,6 +1839,11 @@ icon_state = "asteroidplating" }, /area/station/security/permabrig) +"alq" = ( +/obj/structure/closet, +/obj/effect/spawner/lootdrop/maintenance/two, +/turf/simulated/floor/plating/asteroid/ancient, +/area/station/maintenance/starboard) "alt" = ( /obj/machinery/camera{ c_tag = "Prison Central"; @@ -6609,6 +6614,7 @@ /area/station/security/permabrig) "aQR" = ( /obj/structure/closet/crate, +/obj/effect/spawner/lootdrop/maintenance/two, /turf/simulated/floor/plating, /area/station/maintenance/maintcentral) "aQS" = ( @@ -14849,6 +14855,7 @@ dir = 8 }, /obj/structure/closet, +/obj/effect/spawner/lootdrop/maintenance/two, /turf/simulated/floor/plating, /area/station/maintenance/fsmaint2) "bEP" = ( @@ -16885,6 +16892,7 @@ /area/station/command/bridge) "bMX" = ( /obj/structure/closet/wardrobe/mixed, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating, /area/station/maintenance/port) "bMY" = ( @@ -17189,6 +17197,7 @@ dir = 4 }, /obj/structure/closet/emcloset, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating{ icon_state = "asteroidplating" }, @@ -19083,7 +19092,6 @@ pixel_x = 24; name = "east bump" }, -/obj/structure/disposalpipe/segment, /obj/effect/spawner/random_spawners/dirt_often, /turf/simulated/floor/plasteel{ icon_state = "cafeteria" @@ -19255,6 +19263,7 @@ }, /obj/effect/decal/cleanable/cobweb, /obj/structure/closet, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating, /area/station/maintenance/fore2) "bWl" = ( @@ -19526,6 +19535,7 @@ "bXu" = ( /obj/structure/rack, /obj/item/pickaxe/emergency, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating, /area/station/maintenance/fore2) "bXv" = ( @@ -20176,6 +20186,11 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/fore2) +"ccV" = ( +/obj/structure/rack, +/obj/effect/spawner/lootdrop/maintenance/two, +/turf/simulated/floor/plating/asteroid/ancient, +/area/station/maintenance/fore2) "ccW" = ( /turf/simulated/mineral/ancient, /area/mine/unexplored/cere/research) @@ -21976,10 +21991,10 @@ d2 = 8; icon_state = "4-8" }, -/obj/structure/disposalpipe/sortjunction{ - dir = 2; - name = "disposal pipe - Chemistry"; - sort_type_txt = "11" +/obj/structure/disposalpipe/sortjunction/reversed{ + name = "disposal pipe - Medbay"; + sort_type_txt = "9"; + dir = 8 }, /turf/simulated/floor/plasteel{ icon_state = "cafeteria" @@ -22079,6 +22094,7 @@ /obj/structure/closet/emcloset, /obj/machinery/light/small, /obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating, /area/station/maintenance/port) "coO" = ( @@ -23749,6 +23765,7 @@ "czP" = ( /obj/structure/closet/crate, /obj/item/pickaxe, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating/asteroid/ancient, /area/station/maintenance/apmaint) "czQ" = ( @@ -31090,6 +31107,7 @@ /area/station/maintenance/disposal/west) "doo" = ( /obj/structure/closet/emcloset, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating/asteroid/ancient, /area/station/maintenance/fpmaint) "dos" = ( @@ -33825,6 +33843,7 @@ /area/station/maintenance/starboard) "dCU" = ( /obj/structure/closet/emcloset, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating/asteroid/ancient, /area/station/maintenance/starboard) "dCV" = ( @@ -35470,6 +35489,7 @@ "eeZ" = ( /obj/structure/closet/crate, /obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating, /area/station/maintenance/fore2) "efa" = ( @@ -35983,6 +36003,7 @@ /area/station/hallway/primary/central/west) "eot" = ( /obj/structure/closet, +/obj/effect/spawner/lootdrop/maintenance/two, /turf/simulated/floor/plating, /area/station/maintenance/maintcentral) "eoz" = ( @@ -36240,6 +36261,7 @@ /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 5 }, +/obj/effect/spawner/lootdrop/maintenance/two, /turf/simulated/floor/plating, /area/station/maintenance/storage) "etG" = ( @@ -36307,6 +36329,7 @@ /area/station/service/clown) "eux" = ( /obj/structure/closet/emcloset, +/obj/effect/spawner/lootdrop/maintenance/two, /turf/simulated/floor/plating/asteroid/ancient, /area/station/maintenance/maintcentral) "euL" = ( @@ -36637,6 +36660,7 @@ /obj/structure/closet/crate{ name = "top secret mime supplies" }, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating{ icon_state = "asteroidplating" }, @@ -37705,6 +37729,11 @@ }, /turf/simulated/floor/grass, /area/station/hallway/spacebridge/scidock) +"eTI" = ( +/obj/structure/table, +/obj/effect/spawner/lootdrop/maintenance, +/turf/simulated/floor/plating/asteroid/ancient, +/area/station/maintenance/port) "eTJ" = ( /obj/item/kirbyplants, /obj/structure/disposalpipe/segment{ @@ -38204,6 +38233,7 @@ /obj/structure/disposalpipe/segment/corner{ dir = 8 }, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating{ icon_state = "asteroidplating" }, @@ -39912,11 +39942,6 @@ }, /area/station/hallway/primary/aft/west) "fLp" = ( -/obj/structure/disposalpipe/sortjunction{ - dir = 2; - name = "disposal pipe - CMO Office"; - sort_type_txt = "10" - }, /obj/effect/spawner/random_spawners/dirt_often, /obj/machinery/atmospherics/unary/vent_pump/on{ dir = 8 @@ -40732,10 +40757,6 @@ icon_state = "whitegreen" }, /area/station/public/sleep) -"fYD" = ( -/obj/structure/rack, -/turf/simulated/floor/plating/asteroid/ancient, -/area/station/maintenance/apmaint) "fYG" = ( /obj/machinery/door/airlock/public/glass{ name = "Walkway" @@ -41262,6 +41283,8 @@ /obj/structure/disposalpipe/segment/corner{ dir = 1 }, +/obj/structure/closet, +/obj/effect/spawner/lootdrop/maintenance/two, /turf/simulated/floor/plating{ icon_state = "asteroidplating" }, @@ -41465,9 +41488,6 @@ name = "Port Asteroid Maintenance" }, /obj/effect/mapping_helpers/airlock/access/all/engineering/maintenance, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/structure/disposalpipe/segment{ dir = 4 }, @@ -41549,14 +41569,6 @@ icon_state = "wood-broken7" }, /area/station/maintenance/asmaint) -"gqG" = ( -/obj/structure/disposalpipe/segment/corner{ - dir = 4 - }, -/turf/simulated/floor/plasteel{ - icon_state = "cafeteria" - }, -/area/station/medical/break_room) "gqH" = ( /obj/structure/cable/orange{ d1 = 1; @@ -43786,6 +43798,7 @@ "hcK" = ( /obj/effect/decal/cleanable/cobweb, /obj/structure/closet/wardrobe/black, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating, /area/station/maintenance/port) "hcT" = ( @@ -44813,6 +44826,7 @@ /area/mine/unexplored/cere/cargo) "huF" = ( /obj/structure/table, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating, /area/station/maintenance/disposal/west) "huM" = ( @@ -44923,6 +44937,7 @@ /area/station/maintenance/disposal/west) "hxc" = ( /obj/structure/closet/crate, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating{ icon_state = "asteroidplating" }, @@ -46588,7 +46603,6 @@ /obj/structure/chair/sofa/corp/right{ dir = 8 }, -/obj/structure/disposalpipe/segment, /turf/simulated/floor/plasteel{ icon_state = "cafeteria" }, @@ -46778,6 +46792,7 @@ /area/station/command/office/ntrep) "ibf" = ( /obj/structure/closet/emcloset, +/obj/effect/spawner/lootdrop/maintenance/two, /turf/simulated/floor/plating, /area/station/maintenance/maintcentral) "ibH" = ( @@ -48016,10 +48031,10 @@ d2 = 8; icon_state = "4-8" }, -/obj/structure/disposalpipe/segment/corner{ - dir = 1 - }, /obj/effect/spawner/random_spawners/dirt_frequent, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /turf/simulated/floor/plasteel{ icon_state = "cafeteria" }, @@ -49289,6 +49304,7 @@ /area/station/maintenance/fore) "iOU" = ( /obj/structure/table/wood, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/wood, /area/station/maintenance/starboard) "iPa" = ( @@ -49913,6 +49929,7 @@ /area/station/science/xenobiology) "iXm" = ( /obj/structure/closet, +/obj/effect/spawner/lootdrop/maintenance/two, /turf/simulated/floor/plating/asteroid/ancient, /area/station/maintenance/fsmaint) "iXt" = ( @@ -50016,6 +50033,7 @@ /area/mine/unexplored/cere/orbiting) "iZd" = ( /obj/structure/closet/emcloset, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating, /area/station/hallway/primary/fore/west) "iZr" = ( @@ -50488,7 +50506,6 @@ dir = 4; pixel_x = 11 }, -/obj/structure/disposalpipe/segment/corner, /turf/simulated/floor/plasteel{ icon_state = "cafeteria" }, @@ -50927,6 +50944,7 @@ /obj/structure/disposalpipe/segment/corner{ dir = 4 }, +/obj/effect/spawner/lootdrop/maintenance/two, /turf/simulated/floor/plating, /area/station/maintenance/disposal/east) "jpP" = ( @@ -52644,16 +52662,6 @@ }, /turf/simulated/floor/plating, /area/station/maintenance/apmaint) -"jOU" = ( -/obj/structure/disposalpipe/sortjunction{ - dir = 2; - name = "disposal pipe - Genetics"; - sort_type_txt = "23" - }, -/turf/simulated/floor/plasteel{ - icon_state = "cafeteria" - }, -/area/station/medical/break_room) "jPa" = ( /obj/structure/grille, /turf/simulated/floor/plating{ @@ -55307,6 +55315,7 @@ "kIn" = ( /obj/structure/table, /obj/item/storage/fancy/cigarettes, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating, /area/station/maintenance/disposal/south) "kIo" = ( @@ -56432,10 +56441,6 @@ icon_state = "redcorner" }, /area/station/hallway/secondary/entry/north) -"kYJ" = ( -/obj/structure/closet/crate, -/turf/simulated/floor/plating, -/area/station/maintenance/storage) "kYN" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, @@ -60579,6 +60584,7 @@ dir = 4 }, /obj/structure/closet/crate, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating, /area/station/maintenance/disposal/east) "mlM" = ( @@ -62181,6 +62187,7 @@ /area/station/maintenance/electrical_shop) "mPu" = ( /obj/structure/table/wood/poker, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/wood{ icon_state = "wood-broken" }, @@ -63160,10 +63167,6 @@ }, /turf/simulated/floor/plating, /area/station/hallway/secondary/entry/north) -"neV" = ( -/obj/structure/closet/crate, -/turf/simulated/floor/plating/asteroid/ancient, -/area/station/maintenance/port) "nfb" = ( /obj/structure/table/glass, /obj/item/storage/box/syringes, @@ -63932,6 +63935,7 @@ d2 = 8; icon_state = "4-8" }, +/obj/effect/mapping_helpers/airlock/access/all/command/general, /turf/simulated/floor/plating, /area/station/engineering/tech_storage) "nta" = ( @@ -63956,6 +63960,11 @@ icon_state = "dark" }, /area/station/turret_protected/ai_upload) +"ntf" = ( +/obj/structure/closet/emcloset, +/obj/effect/spawner/lootdrop/maintenance, +/turf/simulated/floor/plating/asteroid/ancient, +/area/station/maintenance/port) "nto" = ( /obj/effect/spawner/window/reinforced/grilled, /obj/structure/cable/orange, @@ -65217,7 +65226,6 @@ /turf/simulated/wall, /area/station/hallway/primary/aft/west) "nOU" = ( -/obj/structure/disposalpipe/segment, /obj/machinery/door/airlock/maintenance/external{ name = "External Airlock Access" }, @@ -67790,6 +67798,13 @@ }, /turf/simulated/floor/plating, /area/station/turret_protected/aisat/interior/secondary) +"oHm" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/turf/simulated/floor/plasteel{ + icon_state = "cafeteria" + }, +/area/station/medical/break_room) "oIc" = ( /obj/structure/cable{ d2 = 4; @@ -70426,6 +70441,7 @@ }, /obj/structure/rack, /obj/item/stack/rods, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating/asteroid/ancient, /area/station/maintenance/starboard) "pxV" = ( @@ -71427,6 +71443,7 @@ /area/station/command/office/hos) "pOf" = ( /obj/structure/closet/firecloset/full, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating/asteroid/ancient, /area/station/maintenance/fsmaint2) "pOk" = ( @@ -76558,6 +76575,7 @@ /area/station/public/quantum/cargo) "rxg" = ( /obj/structure/closet, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating/asteroid/ancient, /area/station/maintenance/apmaint) "rxi" = ( @@ -85427,9 +85445,6 @@ name = "Engine Room" }, /obj/effect/mapping_helpers/airlock/access/all/engineering/general, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/structure/cable{ d1 = 4; d2 = 8; @@ -85474,6 +85489,16 @@ icon_state = "neutralfull" }, /area/station/hallway/primary/port/east) +"urD" = ( +/obj/structure/disposalpipe/segment, +/obj/structure/chair/stool, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 5 + }, +/turf/simulated/floor/plasteel{ + icon_state = "cafeteria" + }, +/area/station/medical/break_room) "urK" = ( /obj/machinery/mineral/stacking_machine{ output_dir = 2; @@ -85504,15 +85529,6 @@ icon_state = "asteroidplating" }, /area/station/maintenance/port) -"uso" = ( -/obj/structure/disposalpipe/junction{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/turf/simulated/floor/plasteel{ - icon_state = "cafeteria" - }, -/area/station/medical/break_room) "usr" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, @@ -87202,18 +87218,6 @@ }, /turf/simulated/floor/plating, /area/station/command/bridge) -"uSc" = ( -/obj/structure/chair/stool, -/obj/structure/disposalpipe/junction{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 5 - }, -/turf/simulated/floor/plasteel{ - icon_state = "cafeteria" - }, -/area/station/medical/break_room) "uSr" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 5 @@ -87878,10 +87882,6 @@ /obj/structure/disposalpipe/junction/reversed, /turf/simulated/floor/plating, /area/station/maintenance/starboard) -"vbu" = ( -/obj/structure/closet, -/turf/simulated/floor/plating/asteroid/ancient, -/area/station/maintenance/fpmaint) "vbD" = ( /obj/machinery/atmospherics/pipe/manifold/hidden, /turf/simulated/floor/plasteel{ @@ -95118,6 +95118,7 @@ "xiV" = ( /obj/structure/closet/emcloset, /obj/effect/decal/cleanable/cobweb, +/obj/effect/spawner/lootdrop/maintenance, /turf/simulated/floor/plating/asteroid/ancient, /area/station/maintenance/port) "xja" = ( @@ -108722,7 +108723,7 @@ xJa xJa rUo nxA -vbu +bzh xJa cRv rNK @@ -108820,7 +108821,7 @@ vtY uCK vtY uCK -uCK +eTI vtY ccW ccW @@ -110879,7 +110880,7 @@ uCK uCK uCK uCK -uCK +bWG vtY vtY ccW @@ -111574,7 +111575,7 @@ rNK rNK pXy pXy -ccx +ntf eCI aue uaW @@ -111654,7 +111655,7 @@ vtY vtY uCK uCK -neV +taQ vtY ccW rWw @@ -121944,7 +121945,7 @@ chX ciG gPL pQN -sKh +wQl nta cGd dzs @@ -124257,7 +124258,7 @@ njR ciG gPL pQN -fYD +tnj clq cGd xPU @@ -125148,7 +125149,7 @@ uEU abW abW wDs -bbc +ccV rVx qLN aJp @@ -130134,7 +130135,7 @@ bWU bXA bYe bDR -kYJ +kyo oqB cRo kzf @@ -146851,7 +146852,7 @@ iJa imG imG imG -imG +gge aXn imG vRX @@ -148620,8 +148621,8 @@ bHr uhF mqe dYc -uso -uSc +oHm +urD xQF uhF nDq @@ -148876,8 +148877,8 @@ xeq cdI uhF owY -gqG -jOU +tKE +tKE fLp cnW gxB @@ -151461,7 +151462,7 @@ itf dCS xAV ozK -gFg +aUU wyL jeB hpB @@ -152737,7 +152738,7 @@ mOC frg lWu gSQ -gSQ +alq itf itf gSQ diff --git a/_maps/map_files/stations/deltastation.dmm b/_maps/map_files/stations/deltastation.dmm index e890932b2be..37a1dedd289 100644 --- a/_maps/map_files/stations/deltastation.dmm +++ b/_maps/map_files/stations/deltastation.dmm @@ -10845,7 +10845,6 @@ /area/station/maintenance/incinerator) "aLk" = ( /obj/structure/disposalpipe/segment, -/obj/structure/disposalpipe/segment, /obj/effect/turf_decal/stripes/line{ dir = 8 }, @@ -11828,7 +11827,6 @@ }, /area/station/service/bar) "aOd" = ( -/obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/visible{ dir = 10 }, @@ -70042,9 +70040,6 @@ /area/station/command/office/hop) "gFa" = ( /obj/machinery/door/firedoor, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/effect/turf_decal/delivery, /obj/structure/disposalpipe/segment{ dir = 4 @@ -82625,15 +82620,6 @@ }, /area/station/security/prison/cell_block) "ont" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/machinery/light{ - dir = 1 - }, /obj/structure/disposalpipe/segment{ dir = 4 }, diff --git a/_maps/map_files/stations/metastation.dmm b/_maps/map_files/stations/metastation.dmm index e45238c442c..2876dab601b 100644 --- a/_maps/map_files/stations/metastation.dmm +++ b/_maps/map_files/stations/metastation.dmm @@ -71465,20 +71465,6 @@ /obj/effect/landmark/damageturf, /turf/simulated/floor/plating, /area/station/maintenance/apmaint) -"oDZ" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/simulated/floor/plating, -/area/station/maintenance/port) "oEe" = ( /obj/machinery/atmospherics/trinary/filter{ dir = 4; @@ -115249,7 +115235,7 @@ nBj cgt cdT wfa -oDZ +bqQ cCj cdT kNJ diff --git a/code/__DEFINES/combat_defines.dm b/code/__DEFINES/combat_defines.dm index ee2ec5345af..01e0c8990c7 100644 --- a/code/__DEFINES/combat_defines.dm +++ b/code/__DEFINES/combat_defines.dm @@ -157,3 +157,10 @@ #define STATUS_EFFECT_CONSTANT * 20 #define IS_HORIZONTAL(x) x.body_position + +/// Compatible firemode is in the gun. Wait until it's held in the user hands. +#define AUTOFIRE_STAT_IDLE (1<<0) +/// Gun is active and in the user hands. Wait until user does a valid click. +#define AUTOFIRE_STAT_ALERT (1<<1) +/// Gun is shooting. +#define AUTOFIRE_STAT_FIRING (1<<2) diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 05150f92552..f10dc5d3334 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -219,8 +219,17 @@ ///////////////// -///from base of client/Click(): (atom/target, atom/location, control, params, mob/user) +// /client signals + +/// from base of client/Click(): (atom/target, atom/location, control, params, mob/user) #define COMSIG_CLIENT_CLICK "atom_client_click" +/// from base of client/MouseDown(): (/client, object, location, control, params) +#define COMSIG_CLIENT_MOUSEDOWN "client_mousedown" +/// from base of client/MouseUp(): (/client, object, location, control, params) +#define COMSIG_CLIENT_MOUSEUP "client_mouseup" + #define COMPONENT_CLIENT_MOUSEUP_INTERCEPT (1<<0) +/// from base of client/MouseUp(): (/client, object, location, control, params) +#define COMSIG_CLIENT_MOUSEDRAG "client_mousedrag" ///from base of area/Entered(): (/area) #define COMSIG_ENTER_AREA "enter_area" @@ -708,11 +717,16 @@ // /obj/item/gun signals -///called in /obj/item/gun/process_fire (user, target, params, zone_override) +/// called in /obj/item/gun/process_fire (user, target, params, zone_override) #define COMSIG_MOB_FIRED_GUN "mob_fired_gun" - -///called in /obj/item/gun/process_fire (user, target) +/// called in /obj/item/gun/process_fire (user, target) #define COMSIG_GUN_FIRED "gun_fired" +/// called in /datum/component/automatic_fire/proc/on_mouse_down: (client/clicker, atom/target, turf/location, control, params) +#define COMSIG_AUTOFIRE_ONMOUSEDOWN "autofire_onmousedown" + #define COMPONENT_AUTOFIRE_ONMOUSEDOWN_BYPASS (1<<0) +/// called in /datum/component/automatic_fire/proc/process_shot(): (atom/target, mob/living/shooter, allow_akimbo, params) +#define COMSIG_AUTOFIRE_SHOT "autofire_shot" + #define COMPONENT_AUTOFIRE_SHOT_SUCCESS (1<<0) // /obj/item/grenade signals @@ -1044,3 +1058,6 @@ // Sent when a mob spawner is attacked directly or via projectile. #define COMSIG_SPAWNER_SET_TARGET "spawner_set_target" + +/// Used by admin-tooling to remove radiation +#define COMSIG_ADMIN_DECONTAMINATE "admin_decontaminate" diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 4f808a9ad0a..62d3df6514e 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -58,6 +58,10 @@ #define isclothing(A) (istype(A, /obj/item/clothing)) +#define isprojectile(A) (istype(A, /obj/item/projectile)) + +#define isgun(A) (istype(A, /obj/item/gun)) + #define is_pen(W) (istype(W, /obj/item/pen) || istype(W, /obj/item/flashlight/pen)) #define is_pda(W) (istype(W, /obj/item/pda)) diff --git a/code/__DEFINES/martial_arts.dm b/code/__DEFINES/martial_arts.dm index 4e8111e0573..566c7a7a714 100644 --- a/code/__DEFINES/martial_arts.dm +++ b/code/__DEFINES/martial_arts.dm @@ -14,4 +14,4 @@ #define MARTIAL_COMBO_STEP_HELP "Help" // A check used for all act types. Such as disarm_act -#define MARTIAL_ARTS_ACT_CHECK if((. = ..()) != FALSE) return . +#define MARTIAL_ARTS_ACT_CHECK if((. = ..()) != FALSE) return diff --git a/code/__DEFINES/mob_defines.dm b/code/__DEFINES/mob_defines.dm index 1d66a0504ff..ebc22191907 100644 --- a/code/__DEFINES/mob_defines.dm +++ b/code/__DEFINES/mob_defines.dm @@ -263,8 +263,6 @@ #define ispathsilicon(A) (ispath(A, /mob/living/silicon)) #define ispathanimal(A) (ispath(A, /mob/living/simple_animal)) -#define isAutoAnnouncer(A) (istype((A), /mob/living/automatedannouncer)) - #define iscameramob(A) (istype((A), /mob/camera)) #define isAIEye(A) (istype((A), /mob/camera/aiEye)) #define isovermind(A) (istype((A), /mob/camera/blob)) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index c30ca477cae..59da6920026 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -242,7 +242,6 @@ continue if(is_same_root_atom(M, speaker_coverage[ear])) . |= M - return . /proc/inLineOfSight(X1,Y1,X2,Y2,Z=1,PX1=16.5,PY1=16.5,PX2=16.5,PY2=16.5) var/turf/T diff --git a/code/__HELPERS/mob_helpers.dm b/code/__HELPERS/mob_helpers.dm index 42a2c024560..d4e50baa361 100644 --- a/code/__HELPERS/mob_helpers.dm +++ b/code/__HELPERS/mob_helpers.dm @@ -189,7 +189,6 @@ return min(max(. + rand(-25, 25), -185), 34) else if(species == "Vox") . = rand(1, 6) - return . /proc/skintone2racedescription(tone, species = "Human") if(species == "Human") @@ -609,7 +608,7 @@ GLOBAL_LIST_EMPTY(do_after_once_tracker) var/viewX var/viewY if(isnum(view)) - var/totalviewrange = 1 + 2 * view + var/totalviewrange = (view < 0 ? -1 : 1) + 2 * view viewX = totalviewrange viewY = totalviewrange else if(istext(view)) @@ -625,6 +624,12 @@ GLOBAL_LIST_EMPTY(do_after_once_tracker) return list(viewX, viewY) +/proc/in_view_range(mob/user, atom/A) + var/list/view_range = getviewsize(user.client.view) + var/turf/source = get_turf(user) + var/turf/target = get_turf(A) + return ISINRANGE(target.x, source.x - view_range[1], source.x + view_range[1]) && ISINRANGE(target.y, source.y - view_range[2], source.y + view_range[2]) + //Used in chemical_mob_spawn. Generates a random mob based on a given gold_core_spawnable value. /proc/create_random_mob(spawn_location, mob_class = HOSTILE_SPAWN) var/static/list/mob_spawn_meancritters = list() // list of possible hostile mobs diff --git a/code/__HELPERS/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm index 8c7f9714d4b..ed3c6627575 100644 --- a/code/__HELPERS/sanitize_values.dm +++ b/code/__HELPERS/sanitize_values.dm @@ -12,9 +12,12 @@ return default /proc/sanitize_inlist(value, list/List, default) - if(value in List) return value - if(default) return default - if(length(List)) return pick(List) + if(value in List) + return value + if(default) + return default + if(length(List)) + return pick(List) /proc/sanitize_json(json_input) if(length(json_input) && istext(json_input)) @@ -35,19 +38,25 @@ return default /proc/sanitize_hexcolor(color, default="#000000") - if(!istext(color)) return default + if(!istext(color)) + return default var/len = length(color) - if(len != 7 && len !=4) return default - if(text2ascii(color,1) != 35) return default //35 is the ascii code for "#" + if(len != 7 && len !=4) + return default + if(text2ascii(color, 1) != 35) + return default //35 is the ascii code for "#" . = "#" for(var/i=2,i<=len,i++) var/ascii = text2ascii(color,i) switch(ascii) - if(48 to 57) . += ascii2text(ascii) //numbers 0 to 9 - if(97 to 102) . += ascii2text(ascii) //letters a to f - if(65 to 70) . += ascii2text(ascii+32) //letters A to F - translates to lowercase - else return default - return . + if(48 to 57) + . += ascii2text(ascii) //numbers 0 to 9 + if(97 to 102) + . += ascii2text(ascii) //letters a to f + if(65 to 70) + . += ascii2text(ascii + 32) //letters A to F - translates to lowercase + else + return default /proc/sanitize_ooccolor(color) var/list/HSL = rgb2hsl(hex2num(copytext(color,2,4)),hex2num(copytext(color,4,6)),hex2num(copytext(color,6,8))) diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index f118fab395f..f5362ea9643 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -193,7 +193,6 @@ if(rights & R_MENTOR) . += "[seperator]+MENTOR" if(rights & R_VIEWRUNTIMES) . += "[seperator]+VIEWRUNTIMES" if(rights & R_MAINTAINER) . += "[seperator]+MAINTAINER" - return . /proc/ui_style2icon(ui_style) switch(ui_style) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 579be0eb83a..636430e1b64 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -323,7 +323,6 @@ if(A.control_disabled) continue . += A - return . //Find an active ai with the least borgs. VERBOSE PROCNAME HUH! /proc/select_active_ai_with_fewest_borgs() @@ -1951,6 +1950,27 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) pixel_x = initialpixelx pixel_y = initialpixely +/// Returns a turf based on text inputs, original turf and viewing client +/proc/parse_caught_click_modifiers(list/modifiers, turf/origin, client/viewing_client) + if(!modifiers) + return + + var/screen_loc = splittext(modifiers["screen-loc"], ",") + var/list/actual_view = getviewsize(viewing_client ? viewing_client.view : world.view) + var/click_turf_x = splittext(screen_loc[1], ":") + var/click_turf_y = splittext(screen_loc[2], ":") + var/click_turf_z = origin.z + + var/click_turf_px = text2num(click_turf_x[2]) + var/click_turf_py = text2num(click_turf_y[2]) + click_turf_x = origin.x + text2num(click_turf_x[1]) - round(actual_view[1] / 2) - 1 + click_turf_y = origin.y + text2num(click_turf_y[1]) - round(actual_view[2] / 2) - 1 + + var/turf/click_turf = locate(clamp(click_turf_x, 1, world.maxx), clamp(click_turf_y, 1, world.maxy), click_turf_z) + LAZYSET(modifiers, "icon-x", "[(click_turf_px - click_turf.pixel_x) + ((click_turf_x - click_turf.x) * world.icon_size)]") + LAZYSET(modifiers, "icon-y", "[(click_turf_py - click_turf.pixel_y) + ((click_turf_y - click_turf.y) * world.icon_size)]") + return click_turf + /proc/params2turf(scr_loc, turf/origin, client/C) if(!scr_loc) return null diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm index 84f87e5bfd5..9f40c657b95 100644 --- a/code/_onclick/drag_drop.dm +++ b/code/_onclick/drag_drop.dm @@ -47,4 +47,71 @@ actually if you do something in that proc like changing user location or whateve to inform the game this action was expected and its fine */ /atom/proc/MouseDrop_T(atom/dropping, mob/user, params) // return TRUE if you want to prevent us click the object after it - return + return FALSE + +/client/MouseDown(datum/object, location, control, params) + if(QDELETED(object)) // Yep, you can click on qdeleted things before they have time to nullspace. Fun. + return + SEND_SIGNAL(src, COMSIG_CLIENT_MOUSEDOWN, object, location, control, params) + if(mouse_down_icon) + mouse_pointer_icon = mouse_down_icon + var/delay = mob.CanMobAutoclick(object, location, params) + if(delay) + selected_target[1] = object + selected_target[2] = params + while(selected_target[1]) + Click(selected_target[1], location, control, selected_target[2]) + sleep(delay) + +/client/MouseUp(object, location, control, params) + if(SEND_SIGNAL(src, COMSIG_CLIENT_MOUSEUP, object, location, control, params) & COMPONENT_CLIENT_MOUSEUP_INTERCEPT) + click_intercept_time = world.time + if(mouse_up_icon) + mouse_pointer_icon = mouse_up_icon + selected_target[1] = null + +/mob/proc/CanMobAutoclick(object, location, params) + return FALSE + +/mob/living/carbon/CanMobAutoclick(atom/object, location, params) + if(!object.IsAutoclickable()) + return FALSE + var/obj/item/active_item = get_active_hand() + return active_item?.CanItemAutoclick(object, location, params) + +/obj/item/proc/CanItemAutoclick(object, location, params) + return FALSE + +/atom/proc/IsAutoclickable() + return TRUE + +/obj/screen/IsAutoclickable() + return FALSE + +/obj/screen/click_catcher/IsAutoclickable() + return TRUE + +// The actual arguments of this: +// MouseDrag(src_object as null|atom in usr.client, +// over_object as null|atom in usr.client, +// src_location as null|turf|text in usr.client, +// over_location as null|turf|text in usr.client, +// src_control as text, over_control as text, params as text) +/client/MouseDrag(src_object, atom/over_object, src_location, turf/over_location, src_control, over_control, params) + var/list/modifiers = params2list(params) + if(!drag_start) // If we're just starting to drag + drag_start = world.time + drag_details = modifiers.Copy() + mouseParams = params + mouse_location_UID = isturf(over_location) ? over_location.UID() : over_location + mouse_object_UID = over_object?.UID() + if(selected_target[1] && over_object?.IsAutoclickable()) + selected_target[1] = over_object + selected_target[2] = params + SEND_SIGNAL(src, COMSIG_CLIENT_MOUSEDRAG, src_object, over_object, src_location, over_location, src_control, over_control, params) + return ..() + +/client/MouseDrop(atom/src_object, atom/over_object, atom/src_location, atom/over_location, src_control, over_control, params) + ..() + drag_start = 0 + drag_details = null diff --git a/code/controllers/subsystem/SSradiation.dm b/code/controllers/subsystem/SSradiation.dm index 540e56ce19a..c30f40a1363 100644 --- a/code/controllers/subsystem/SSradiation.dm +++ b/code/controllers/subsystem/SSradiation.dm @@ -13,6 +13,8 @@ PROCESSING_SUBSYSTEM_DEF(radiation) var/rad_cache_update_interval = 5 SECONDS var/list/turf_rad_cache = list() var/list/prev_rad_cache = list() + /// Lazy list of all radioactive components + var/list/all_radiations /datum/controller/subsystem/processing/radiation/proc/warn(datum/component/radioactive/contamination) diff --git a/code/controllers/subsystem/SSticker.dm b/code/controllers/subsystem/SSticker.dm index 6a9bd55d688..c08699c48ee 100644 --- a/code/controllers/subsystem/SSticker.dm +++ b/code/controllers/subsystem/SSticker.dm @@ -81,9 +81,9 @@ SUBSYSTEM_DEF(ticker) switch(current_state) if(GAME_STATE_STARTUP) // This is ran as soon as the MC starts firing, and should only run ONCE, unless startup fails - round_start_time = world.time + (GLOB.configuration.general.lobby_time SECONDS) pregame_timeleft = GLOB.configuration.general.lobby_time SECONDS - to_chat(world, "Welcome to the pre-game lobby!") + round_start_time = world.time + pregame_timeleft + to_chat(world, "Welcome to the pre-game lobby!") to_chat(world, "Please, setup your character and select ready. Game will start in [GLOB.configuration.general.lobby_time] seconds") current_state = GAME_STATE_PREGAME fire() // TG says this is a good idea @@ -95,12 +95,9 @@ SUBSYSTEM_DEF(ticker) return // This is so we dont have sleeps in controllers, because that is a bad, bad thing - if(!delay_end) - pregame_timeleft = max(0, round_start_time - world.time) // Normal lobby countdown when roundstart was not delayed - else - pregame_timeleft = max(0, pregame_timeleft - wait) // If roundstart was delayed, we should resume the countdown where it left off + pregame_timeleft = max(0, round_start_time - world.time) - if(pregame_timeleft <= 600 && !tipped) // 60 seconds + if(pregame_timeleft <= 1 MINUTES && !tipped) send_tip_of_the_round() tipped = TRUE diff --git a/code/datums/action.dm b/code/datums/action.dm index d85eaa080a3..511865a1c61 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -120,7 +120,8 @@ return if(!status_only) button.name = name - button.desc = desc + if(desc) + button.desc = "[desc] [initial(button.desc)]" if(owner?.hud_used && background_icon_state == ACTION_BUTTON_DEFAULT_BACKGROUND) var/list/settings = owner.hud_used.get_action_buttons_icons() if(button.icon != settings["bg_icon"]) @@ -679,7 +680,7 @@ var/datum/spell/spell = target if(owner) - return spell.can_cast(owner) + return spell.can_cast(owner, show_message = TRUE) return FALSE /datum/action/spell_action/apply_unavailable_effect(atom/movable/screen/movable/action_button/button) diff --git a/code/datums/components/fullauto.dm b/code/datums/components/fullauto.dm new file mode 100644 index 00000000000..cfd4da69ce1 --- /dev/null +++ b/code/datums/components/fullauto.dm @@ -0,0 +1,325 @@ +#define AUTOFIRE_MOUSEUP 0 +#define AUTOFIRE_MOUSEDOWN 1 + +/datum/component/automatic_fire + var/client/clicker + var/mob/living/shooter + var/atom/target + var/turf/target_loc // For dealing with locking on targets due to BYOND engine limitations (the mouse input only happening when mouse moves). + var/autofire_stat = AUTOFIRE_STAT_IDLE + var/mouse_parameters + /// Time between individual shots. + var/autofire_shot_delay = 0.3 SECONDS + /// This seems hacky but there can be two MouseDown() without a MouseUp() in between if the user holds click and uses alt+tab, printscreen or similar. + var/mouse_status = AUTOFIRE_MOUSEUP + /// Should dual wielding be allowed? + var/allow_akimbo + + /// windup autofire vars + /// Whether the delay between shots increases over time, simulating a spooling weapon + var/windup_autofire = FALSE + /// the reduction to shot delay for windup + var/current_windup_reduction = 0 + /// the percentage of autfire_shot_delay that is added to current_windup_reduction + var/windup_autofire_reduction_multiplier = 0.3 + /// How high of a reduction that current_windup_reduction can reach + var/windup_autofire_cap = 0.3 + /// How long it takes for weapons that have spooled-up to reset back to the original firing speed + var/windup_spindown = 3 SECONDS + /// Timer for tracking the spindown reset timings + var/timerid + COOLDOWN_DECLARE(next_shot_cd) + +/datum/component/automatic_fire/Initialize(autofire_shot_delay, windup_autofire, windup_autofire_reduction_multiplier, windup_autofire_cap, windup_spindown, allow_akimbo = TRUE) + . = ..() + if(!isgun(parent)) + return COMPONENT_INCOMPATIBLE + var/obj/item/gun = parent + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(wake_up)) + if(autofire_shot_delay) + src.autofire_shot_delay = autofire_shot_delay + src.allow_akimbo = allow_akimbo + if(windup_autofire) + src.windup_autofire = windup_autofire + src.windup_autofire_reduction_multiplier = windup_autofire_reduction_multiplier + src.windup_autofire_cap = windup_autofire_cap + src.windup_spindown = windup_spindown + if(autofire_stat == AUTOFIRE_STAT_IDLE && ismob(gun.loc)) + var/mob/user = gun.loc + wake_up(src, user) + +/datum/component/automatic_fire/Destroy() + autofire_off() + return ..() + +/datum/component/automatic_fire/process(seconds_per_tick) + if(autofire_stat != AUTOFIRE_STAT_FIRING) + STOP_PROCESSING(SSprojectiles, src) + return + process_shot() + +/datum/component/automatic_fire/proc/wake_up(datum/source, mob/user, slot) + SIGNAL_HANDLER // COMSIG_ITEM_EQUIPPED + + if(autofire_stat == AUTOFIRE_STAT_ALERT) + return // We've updated the firemode. No need for more. + if(autofire_stat == AUTOFIRE_STAT_FIRING) + stop_autofiring() // Let's stop shooting to avoid issues. + return + if(user.is_holding(parent)) + autofire_on(user.client) + +// There is a gun and there is a user wielding it. The component now waits for the mouse click. +/datum/component/automatic_fire/proc/autofire_on(client/user_client) + if(autofire_stat != AUTOFIRE_STAT_IDLE) + return + autofire_stat = AUTOFIRE_STAT_ALERT + if(!QDELETED(user_client)) + clicker = user_client + shooter = user_client.mob + RegisterSignal(user_client, COMSIG_CLIENT_MOUSEDOWN, PROC_REF(on_mouse_down)) + if(!QDELETED(shooter)) + RegisterSignal(shooter, COMSIG_MOB_LOGOUT, PROC_REF(autofire_off)) + UnregisterSignal(shooter, COMSIG_MOB_LOGIN) + RegisterSignal(parent, list(COMSIG_PARENT_QDELETING, COMSIG_ITEM_DROPPED), PROC_REF(autofire_off)) + parent.RegisterSignal(src, COMSIG_AUTOFIRE_ONMOUSEDOWN, TYPE_PROC_REF(/obj/item/gun, autofire_bypass_check)) + parent.RegisterSignal(parent, COMSIG_AUTOFIRE_SHOT, TYPE_PROC_REF(/obj/item/gun, do_autofire)) + +/datum/component/automatic_fire/proc/autofire_off(datum/source) + SIGNAL_HANDLER // COMSIG_MOB_LOGOUT + + if(autofire_stat == AUTOFIRE_STAT_IDLE) + return + if(autofire_stat == AUTOFIRE_STAT_FIRING) + stop_autofiring() + + autofire_stat = AUTOFIRE_STAT_IDLE + + if(!QDELETED(clicker)) + UnregisterSignal(clicker, list(COMSIG_CLIENT_MOUSEDOWN, COMSIG_CLIENT_MOUSEUP, COMSIG_CLIENT_MOUSEDRAG)) + mouse_status = AUTOFIRE_MOUSEUP // In regards to the component there's no click anymore to care about. + clicker = null + if(!QDELETED(shooter)) + RegisterSignal(shooter, COMSIG_MOB_LOGIN, PROC_REF(on_client_login)) + UnregisterSignal(shooter, COMSIG_MOB_LOGOUT) + UnregisterSignal(parent, list(COMSIG_PARENT_QDELETING, COMSIG_ITEM_DROPPED)) + shooter = null + parent.UnregisterSignal(parent, COMSIG_AUTOFIRE_SHOT) + parent.UnregisterSignal(src, COMSIG_AUTOFIRE_ONMOUSEDOWN) + +/datum/component/automatic_fire/proc/on_client_login(mob/source) + SIGNAL_HANDLER // COMSIG_MOB_LOGIN + if(!source.client) + return + if(source.is_holding(parent)) + autofire_on(source.client) + +/datum/component/automatic_fire/proc/on_mouse_down(client/source, atom/_target, turf/location, control, params) + SIGNAL_HANDLER // COMSIG_CLIENT_MOUSEDOWN + + var/list/modifiers = params2list(params) // If they're shift+clicking, for example, let's not have them accidentally shoot. + + if(modifiers["shift"]) + return + if(modifiers["ctrl"]) + return + if(modifiers["middle"]) + return + if(modifiers["right"]) + return + if(modifiers["alt"]) + return + if(source.mob.in_throw_mode) + return + if(!isturf(source.mob.loc)) // No firing inside lockers and stuff. + return + if(get_dist(source.mob, _target) < 2) // Adjacent clicking. + return + + if(isnull(location) || istype(_target, /obj/screen)) // Clicking on a screen object. + if(_target.plane != CLICKCATCHER_PLANE) // The clickcatcher is a special case. We want the click to trigger then, under it. + return // If we click and drag on our worn backpack, for example, we want it to open instead. + _target = parse_caught_click_modifiers(modifiers, get_turf(source.eye), source) + params = list2params(modifiers) + if(!_target) + CRASH("Failed to get the turf under clickcatcher") + + if(SEND_SIGNAL(src, COMSIG_AUTOFIRE_ONMOUSEDOWN, source, _target, location, control, params) & COMPONENT_AUTOFIRE_ONMOUSEDOWN_BYPASS) + return + + source.click_intercept_time = world.time // From this point onwards Click() will no longer be triggered. + + if(autofire_stat == AUTOFIRE_STAT_IDLE) + CRASH("on_mouse_down() called with [autofire_stat] autofire_stat") + if(autofire_stat == AUTOFIRE_STAT_FIRING) + stop_autofiring() // This can happen if we click and hold and then alt+tab, printscreen or other such action. MouseUp won't be called then and it will keep autofiring. + + target = _target + target_loc = get_turf(target) + mouse_parameters = params + INVOKE_ASYNC(src, PROC_REF(start_autofiring)) + +/datum/component/automatic_fire/proc/start_autofiring() + if(autofire_stat == AUTOFIRE_STAT_FIRING) + return + autofire_stat = AUTOFIRE_STAT_FIRING + + clicker.mouse_override_icon = 'icons/effects/mouse_pointers/weapon_pointer.dmi' + clicker.mouse_pointer_icon = clicker.mouse_override_icon + + if(mouse_status == AUTOFIRE_MOUSEUP) // See mouse_status definition for the reason for this. + RegisterSignal(clicker, COMSIG_CLIENT_MOUSEUP, PROC_REF(on_mouse_up)) + mouse_status = AUTOFIRE_MOUSEDOWN + + RegisterSignal(shooter, COMSIG_MOB_SWAPPED_HANDS, PROC_REF(stop_autofiring)) + + if(isgun(parent)) + var/obj/item/gun/shoota = parent + if(!shoota.on_autofire_start(shooter)) // This is needed because the minigun has a do_after before firing and signals are async. + stop_autofiring() + return + + if(autofire_stat != AUTOFIRE_STAT_FIRING) + return // Things may have changed while on_autofire_start() was being processed, due to do_after's sleep. + + if(!process_shot()) // First shot is processed instantly. + return // If it fails, such as when the gun is empty, then there's no need to schedule a second shot. + + START_PROCESSING(SSprojectiles, src) + RegisterSignal(clicker, COMSIG_CLIENT_MOUSEDRAG, PROC_REF(on_mouse_drag)) + +/datum/component/automatic_fire/proc/on_mouse_up(datum/source, atom/object, turf/location, control, params) + SIGNAL_HANDLER // COMSIG_CLIENT_MOUSEUP + + UnregisterSignal(clicker, COMSIG_CLIENT_MOUSEUP) + mouse_status = AUTOFIRE_MOUSEUP + if(autofire_stat == AUTOFIRE_STAT_FIRING) + stop_autofiring() + return COMPONENT_CLIENT_MOUSEUP_INTERCEPT + +/datum/component/automatic_fire/proc/stop_autofiring(datum/source, atom/object, turf/location, control, params) + SIGNAL_HANDLER // COMSIG_MOB_SWAPPED_HANDS + + if(autofire_stat != AUTOFIRE_STAT_FIRING) + return + + STOP_PROCESSING(SSprojectiles, src) + autofire_stat = AUTOFIRE_STAT_ALERT + if(clicker) + clicker.mouse_override_icon = null + clicker.mouse_pointer_icon = clicker.mouse_override_icon + UnregisterSignal(clicker, COMSIG_CLIENT_MOUSEDRAG) + if(!QDELETED(shooter)) + UnregisterSignal(shooter, COMSIG_MOB_SWAPPED_HANDS) + target = null + target_loc = null + mouse_parameters = null + +/datum/component/automatic_fire/proc/on_mouse_drag(client/source, atom/src_object, atom/over_object, turf/src_location, turf/over_location, src_control, over_control, params) + SIGNAL_HANDLER // COMSIG_CLIENT_MOUSEDRAG + + if(isnull(over_location)) // This happens when the mouse is over an inventory or screen object, or on entering deep darkness, for example. + var/list/modifiers = params2list(params) + var/new_target = parse_caught_click_modifiers(modifiers, get_turf(source.eye), source) + params = list2params(modifiers) + mouse_parameters = params + if(!new_target) + if(QDELETED(target)) // No new target acquired, and old one was deleted, get us out of here. + stop_autofiring() + CRASH("on_mouse_drag failed to get the turf under screen object [over_object.type]. Old target was incidentally QDELETED.") + target = get_turf(target) // If previous target wasn't a turf, let's turn it into one to avoid locking onto a potentially moving target. + target_loc = target + CRASH("on_mouse_drag failed to get the turf under screen object [over_object.type]") + target = new_target + target_loc = new_target + return + + target = over_object + target_loc = get_turf(over_object) + mouse_parameters = params + +/datum/component/automatic_fire/proc/process_shot() + if(autofire_stat != AUTOFIRE_STAT_FIRING) + return FALSE + + if(!COOLDOWN_FINISHED(src, next_shot_cd)) + return TRUE + + if(QDELETED(target) || get_turf(target) != target_loc) // Target moved or got destroyed since we last aimed. + target = target_loc // So we keep firing on the emptied tile until we move our mouse and find a new target. + + if(get_dist(shooter, target) <= 0) + target = get_step(shooter, shooter.dir) // Shoot in the direction faced if the mouse is on the same tile as we are. + target_loc = target + else if(!in_view_range(shooter, target)) + stop_autofiring() // Elvis has left the building. + return FALSE + + shooter.face_atom(target) + var/next_delay = autofire_shot_delay + if(windup_autofire) + next_delay = clamp(next_delay - current_windup_reduction, round(autofire_shot_delay * windup_autofire_cap), autofire_shot_delay) + current_windup_reduction = (current_windup_reduction + round(autofire_shot_delay * windup_autofire_reduction_multiplier)) + timerid = addtimer(CALLBACK(src, PROC_REF(windup_reset), FALSE), windup_spindown, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE) + + COOLDOWN_START(src, next_shot_cd, next_delay) + + if(SEND_SIGNAL(parent, COMSIG_AUTOFIRE_SHOT, target, shooter, allow_akimbo, mouse_parameters) & COMPONENT_AUTOFIRE_SHOT_SUCCESS) + return TRUE + + stop_autofiring() + return FALSE + +/// Reset for our windup, resetting everything back to initial values after a variable set amount of time (determined by var/windup_spindown). +/datum/component/automatic_fire/proc/windup_reset(deltimer) + current_windup_reduction = initial(current_windup_reduction) + if(deltimer && timerid) + deltimer(timerid) + +// Gun procs. + +/obj/item/gun/proc/on_autofire_start(mob/living/shooter) + if(semicd || shooter.incapacitated() || !can_trigger_gun(shooter)) + return FALSE + + if(!can_shoot()) + shoot_with_empty_chamber(shooter) + return FALSE + + var/other_hand = shooter.get_organ(shooter.hand ? BODY_ZONE_PRECISE_R_HAND : BODY_ZONE_PRECISE_L_HAND) + if(weapon_weight == WEAPON_HEAVY && (shooter.get_inactive_hand() || !other_hand)) + to_chat(shooter, "You need to use both hands!") + return FALSE + + return TRUE + +/obj/item/gun/proc/autofire_bypass_check(datum/source, client/clicker, atom/target, turf/location, control, params) + SIGNAL_HANDLER // COMSIG_AUTOFIRE_ONMOUSEDOWN + + if(clicker.mob.get_active_hand() != src) + return COMPONENT_AUTOFIRE_ONMOUSEDOWN_BYPASS + +/obj/item/gun/proc/do_autofire(datum/source, atom/target, mob/living/shooter, allow_akimbo, params) + SIGNAL_HANDLER // COMSIG_AUTOFIRE_SHOT + + if(semicd || shooter.incapacitated()) + return NONE + + if(!can_shoot()) + shoot_with_empty_chamber(shooter) + return NONE + + INVOKE_ASYNC(src, PROC_REF(do_autofire_shot), source, target, shooter, allow_akimbo, params) + return COMPONENT_AUTOFIRE_SHOT_SUCCESS // All is well, we can continue shooting. + +/obj/item/gun/proc/do_autofire_shot(datum/source, atom/target, mob/living/shooter, allow_akimbo, params) + var/obj/item/gun/akimbo_gun = shooter.get_inactive_hand() + var/bonus_spread = 0 + if(isgun(akimbo_gun) && weapon_weight < WEAPON_MEDIUM && allow_akimbo) + if(akimbo_gun.weapon_weight < WEAPON_MEDIUM && akimbo_gun.can_trigger_gun(shooter)) + bonus_spread = dual_wield_spread + addtimer(CALLBACK(akimbo_gun, TYPE_PROC_REF(/obj/item/gun, process_fire), target, shooter, TRUE, params, null, bonus_spread), 1) + process_fire(target, shooter, TRUE, params, null, bonus_spread) + +#undef AUTOFIRE_MOUSEUP +#undef AUTOFIRE_MOUSEDOWN diff --git a/code/datums/components/radioactive.dm b/code/datums/components/radioactive.dm index 97d0591c4eb..ba240898e34 100644 --- a/code/datums/components/radioactive.dm +++ b/code/datums/components/radioactive.dm @@ -13,17 +13,17 @@ var/can_contaminate /datum/component/radioactive/Initialize(_strength = 0, _source, _half_life = RAD_HALF_LIFE, _can_contaminate = TRUE) + if(!istype(parent, /atom)) + return COMPONENT_INCOMPATIBLE strength = _strength source = _source hl3_release_date = _half_life can_contaminate = _can_contaminate - if(istype(parent, /atom)) - RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(rad_examine)) - if(isitem(parent)) - RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(rad_attack)) - RegisterSignal(parent, COMSIG_ITEM_ATTACK_OBJ, PROC_REF(rad_attack)) - else - return COMPONENT_INCOMPATIBLE + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(rad_examine)) + RegisterSignal(parent, COMSIG_ADMIN_DECONTAMINATE, PROC_REF(admin_decontaminate)) + if(isitem(parent)) + RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(rad_attack)) + RegisterSignal(parent, COMSIG_ITEM_ATTACK_OBJ, PROC_REF(rad_attack)) if(strength > RAD_MINIMUM_CONTAMINATION) SSradiation.warn(src) //Let's make er glow @@ -31,10 +31,12 @@ var/atom/movable/master = parent master.add_filter("rad_glow", 2, list("type" = "outline", "color" = "#39ff1430", "size" = 2)) addtimer(CALLBACK(src, PROC_REF(glow_loop), master), rand(1, 19)) //Things should look uneven + LAZYADD(SSradiation.all_radiations, src) START_PROCESSING(SSradiation, src) /datum/component/radioactive/Destroy() STOP_PROCESSING(SSradiation, src) + LAZYREMOVE(SSradiation.all_radiations, src) var/atom/movable/master = parent master.remove_filter("rad_glow") return ..() @@ -99,6 +101,17 @@ return strength -= strength / hl3_release_date +/datum/component/radioactive/proc/admin_decontaminate() + SIGNAL_HANDLER + . = TRUE + if(ismob(parent)) + var/mob/M = parent + M.radiation = 0 + if(ismob(source)) + var/mob/M = source + M.radiation = 0 + qdel(src) + #undef RAD_AMOUNT_LOW #undef RAD_AMOUNT_MEDIUM #undef RAD_AMOUNT_HIGH diff --git a/code/datums/components/shielded.dm b/code/datums/components/shielded.dm index effad26c8fe..adbe78c3b7f 100644 --- a/code/datums/components/shielded.dm +++ b/code/datums/components/shielded.dm @@ -158,7 +158,7 @@ var/charge_loss = 1 // how many charges do we lose - if(istype(hitby, /obj/item/projectile)) + if(isprojectile(hitby)) var/obj/item/projectile/P = hitby if(P.shield_buster) charge_loss = 3 diff --git a/code/datums/components/squeak.dm b/code/datums/components/squeak.dm index 7445e577605..c2aef66bcaa 100644 --- a/code/datums/components/squeak.dm +++ b/code/datums/components/squeak.dm @@ -76,7 +76,7 @@ var/obj/item/I = AM if(I.flags & ABSTRACT) return - else if(istype(AM, /obj/item/projectile)) + else if(isprojectile(AM)) var/obj/item/projectile/P = AM if(P.original != parent) return diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index e599974ad1a..dfb66d084f6 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -23,9 +23,7 @@ effect_in = effect if(isnull(effect_out)) effect_out = effect - if(D.start(atom_to_teleport, destination, variance_range, force_teleport, effect_in, effect_out, sound_in, sound_out, bypass_area_flag, safe_turf_pick, do_effect)) - return TRUE - return FALSE + return D.start(atom_to_teleport, destination, variance_range, force_teleport, effect_in, effect_out, sound_in, sound_out, bypass_area_flag, safe_turf_pick, do_effect) /datum/teleport var/atom/movable/teleatom //atom to teleport @@ -166,6 +164,16 @@ playSpecials(curturf,effectin,soundin) + if(isliving(teleatom)) + var/mob/living/target_mob = teleatom + if(target_mob.buckled) + target_mob.buckled.unbuckle_mob(target_mob, force = TRUE) + if(target_mob.has_buckled_mobs()) + target_mob.unbuckle_all_mobs(force = TRUE) + if(ismachinery(target_mob.loc) || istype(target_mob.loc, /obj/item/mecha_parts/mecha_equipment/medical/sleeper)) + var/obj/location = target_mob.loc + location.force_eject_occupant(target_mob) + if(force_teleport) teleatom.forceMove(destturf) playSpecials(destturf,effectout,soundout) @@ -173,13 +181,6 @@ if(teleatom.Move(destturf)) playSpecials(destturf,effectout,soundout) - if(isliving(teleatom)) - var/mob/living/L = teleatom - if(L.buckled) - L.buckled.unbuckle_mob(L, force = TRUE) - if(L.has_buckled_mobs()) - L.unbuckle_all_mobs(force = TRUE) - destarea.Entered(teleatom) return TRUE diff --git a/code/datums/recipe.dm b/code/datums/recipe.dm index 8fb79eed615..8d0f7a7c0a1 100644 --- a/code/datums/recipe.dm +++ b/code/datums/recipe.dm @@ -53,7 +53,6 @@ return 0 if((reagents?(length(reagents)):(0)) < length(avail_reagents.reagent_list)) return -1 - return . /datum/recipe/proc/check_items(obj/container, list/ignored_items = null) //1=precisely, 0=insufficiently, -1=superfluous . = 1 @@ -73,7 +72,6 @@ . = -1 if(length(checklist)) return 0 - return . //general version /datum/recipe/proc/make(obj/container) @@ -118,7 +116,6 @@ r_count = N_r i_count = N_i . = recipe - return . /datum/recipe/proc/get_byproduct() if(byproduct) diff --git a/code/datums/spells/alien_spells/basetype_alien_spell.dm b/code/datums/spells/alien_spells/basetype_alien_spell.dm index 547cba3c438..12d98e8e489 100644 --- a/code/datums/spells/alien_spells/basetype_alien_spell.dm +++ b/code/datums/spells/alien_spells/basetype_alien_spell.dm @@ -32,6 +32,9 @@ Updates the spell's actions on use as well, so they know when they can or can't ..() if(plasma_cost) name = "[name] ([plasma_cost])" + action.name = name + action.desc = desc + action.UpdateButtons() /datum/spell/alien_spell/write_custom_logs(list/targets, mob/user) user.create_log(ATTACK_LOG, "Cast the spell [name]") diff --git a/code/defines/procs/admin_keyname_procs.dm b/code/defines/procs/admin_keyname_procs.dm index ec371a6a6da..166540f7b13 100644 --- a/code/defines/procs/admin_keyname_procs.dm +++ b/code/defines/procs/admin_keyname_procs.dm @@ -68,8 +68,6 @@ . += "/([name])" - return . - /proc/key_name_admin(whom) if(whom) var/datum/whom_datum = whom //As long as it's not null, will be close enough/has the proc UID() that is all that's needed @@ -92,3 +90,7 @@ /proc/log_and_message_admins(message) log_admin("[key_name(usr)] " + message) message_admins("[key_name_admin(usr)] " + message) + +/proc/log_and_message_admins_no_usr(message) + log_admin(message) + message_admins(message) diff --git a/code/game/gamemodes/cult/blood_magic.dm b/code/game/gamemodes/cult/blood_magic.dm index 30370c7d905..5a62abbd8c1 100644 --- a/code/game/gamemodes/cult/blood_magic.dm +++ b/code/game/gamemodes/cult/blood_magic.dm @@ -546,7 +546,7 @@ var/input_rune_key = tgui_input_list(user, "Choose a rune to teleport to", "Rune to Teleport to", potential_runes) //we know what key they picked var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to? - if(QDELETED(src) || !user || user.l_hand != src && user.r_hand != src || user.incapacitated() || !actual_selected_rune) + if(QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !actual_selected_rune) return if(HAS_TRAIT(user, TRAIT_FLOORED)) diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index f72ed0d0b15..f8a3ca79d77 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -466,7 +466,7 @@ if(IS_CULTIST(owner) && !owner.holy_check()) // Cultist holding the shield // Hit by a projectile - if(istype(hitby, /obj/item/projectile)) + if(isprojectile(hitby)) var/obj/item/projectile/P = hitby var/shatter_chance = 0 // Percent chance of the shield shattering on a projectile hit var/threshold // Depends on the damage Type (Brute or Burn) diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 6c418ff32b7..3effa71e363 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -851,12 +851,6 @@ selection_deactivated_message = "APC logic thread restarting..." var/is_active = FALSE -/datum/spell/ai_spell/ranged/repair_cyborg/create_new_targeting() - var/datum/spell_targeting/click/T = new - T.allowed_type = /mob/living/silicon/robot - T.try_auto_target = FALSE - return T - /datum/spell/ai_spell/ranged/repair_cyborg/cast(list/targets, mob/user) var/mob/living/silicon/robot/robot_target = targets[1] if(!istype(robot_target)) diff --git a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm index 2322549036a..0eb5a40d52f 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm @@ -216,6 +216,9 @@ occupant = null update_icon(UPDATE_ICON_STATE) +/obj/machinery/abductor/experiment/force_eject_occupant(mob/target) + eject_abductee() + /obj/machinery/abductor/experiment/broken stat = BROKEN diff --git a/code/game/gamemodes/miniantags/morph/spells/morph_spell.dm b/code/game/gamemodes/miniantags/morph/spells/morph_spell.dm index d2581020824..af85ca31121 100644 --- a/code/game/gamemodes/miniantags/morph/spells/morph_spell.dm +++ b/code/game/gamemodes/miniantags/morph/spells/morph_spell.dm @@ -8,6 +8,9 @@ ..() if(hunger_cost) name = "[name] ([hunger_cost])" + action.name = name + action.desc = desc + action.UpdateButtons() /datum/spell/morph_spell/create_new_handler() var/datum/spell_handler/morph/H = new diff --git a/code/game/gamemodes/miniantags/pulsedemon/pulsedemon_abilities.dm b/code/game/gamemodes/miniantags/pulsedemon/pulsedemon_abilities.dm index fb537324b9a..8bb7f2a626c 100644 --- a/code/game/gamemodes/miniantags/pulsedemon/pulsedemon_abilities.dm +++ b/code/game/gamemodes/miniantags/pulsedemon/pulsedemon_abilities.dm @@ -28,10 +28,10 @@ /datum/spell/pulse_demon/proc/update_info() if(locked) name = "[initial(name)] (Locked) ([format_si_suffix(unlock_cost)]W)" - desc = "[initial(desc)] It costs [format_si_suffix(unlock_cost)]W to unlock." + desc = "[initial(desc)] It costs [format_si_suffix(unlock_cost)]W to unlock. Alt-Click this spell to unlock it." else name = "[initial(name)][cast_cost == 0 ? "" : " ([format_si_suffix(cast_cost)]W)"]" - desc = "[initial(desc)][spell_level == level_max ? "" : " It costs [format_si_suffix(upgrade_cost)]W to upgrade."]" + desc = "[initial(desc)][spell_level == level_max ? "" : " It costs [format_si_suffix(upgrade_cost)]W to upgrade. Alt-Click this spell to upgrade it."]" action.name = name action.desc = desc action.UpdateButtons() diff --git a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm index 0bb6122c1b2..0913180f2ef 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm @@ -163,6 +163,9 @@ name = "[initial(name)] ([unlock_amount]E)" else name = "[initial(name)] ([cast_amount]E)" + action.name = name + action.desc = desc + action.UpdateButtons() /datum/spell/aoe/revenant/revert_cast(mob/user) . = ..() diff --git a/code/game/gamemodes/nuclear/nuclear_challenge.dm b/code/game/gamemodes/nuclear/nuclear_challenge.dm index 7acb04f5472..01694f122ce 100644 --- a/code/game/gamemodes/nuclear/nuclear_challenge.dm +++ b/code/game/gamemodes/nuclear/nuclear_challenge.dm @@ -1,9 +1,9 @@ #define CHALLENGE_TELECRYSTALS 1400 -#define CHALLENGE_TIME_LIMIT 6000 +#define CHALLENGE_TIME_LIMIT 10 MINUTES #define CHALLENGE_SCALE_PLAYER 1 // How many player per scaling bonus #define CHALLENGE_SCALE_BONUS 10 // How many TC per scaling bonus #define CHALLENGE_MIN_PLAYERS 50 -#define CHALLENGE_SHUTTLE_DELAY 18000 //30 minutes, so the ops have at least 10 minutes before the shuttle is callable. Gives the nuke ops at least 15 minutes before shuttle arrive. +#define CHALLENGE_SHUTTLE_DELAY 30 MINUTES // So the ops have at least 10 minutes before the shuttle is callable. Gives the nuke ops at least 15 minutes before shuttle arrive. /obj/item/nuclear_challenge name = "Declaration of War (Challenge Mode)" diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index f1b09f316e2..327bc892abf 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -504,7 +504,7 @@ GLOBAL_VAR(bomb_set) update_icon(UPDATE_OVERLAYS) if(!safety) message_admins("[key_name_admin(usr)] engaged a nuclear bomb [ADMIN_JMP(src)]") - if(!is_syndicate) + if(!is_syndicate && SSsecurity_level.get_current_level_as_number() != SEC_LEVEL_EPSILON) SSsecurity_level.set_level(SEC_LEVEL_DELTA) GLOB.bomb_set = TRUE // There can still be issues with this resetting when there are multiple bombs. Not a big deal though for Nuke else diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index f53d3f7ba96..743079d34e5 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -439,7 +439,6 @@ . = ..() if(.) user.mind.AddSpell(new /datum/spell/aoe/conjure/construct(null)) - return . /datum/spellbook_entry/item/wands name = "Wand Assortment" diff --git a/code/game/machinery/clonescanner.dm b/code/game/machinery/clonescanner.dm index ef123acfb4a..83105a45ba4 100644 --- a/code/game/machinery/clonescanner.dm +++ b/code/game/machinery/clonescanner.dm @@ -60,7 +60,7 @@ if(console) console.scanner = null if(occupant) - remove_mob(occupant) + remove_mob() return ..() /obj/machinery/clonescanner/MouseDrop_T(atom/movable/O, mob/user) @@ -84,16 +84,16 @@ if(!occupant) return if(issilicon(user)) - remove_mob(occupant) + remove_mob() return if(!Adjacent(user) || !ishuman(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) return - remove_mob(occupant) + remove_mob() /obj/machinery/clonescanner/relaymove(mob/user) if(user.stat) return - remove_mob(user) + remove_mob() /obj/machinery/clonescanner/proc/try_scan(mob/living/carbon/human/scanned) if(!scanned) @@ -158,10 +158,10 @@ occupant = inserted update_icon(UPDATE_ICON_STATE) -/obj/machinery/clonescanner/proc/remove_mob(mob/living/carbon/human/removed) - if(!istype(removed)) +/obj/machinery/clonescanner/proc/remove_mob() + if(!occupant) return - removed.forceMove(get_turf(loc)) + occupant.forceMove(get_turf(loc)) occupant = null update_scan_status() update_icon(UPDATE_ICON_STATE) @@ -192,3 +192,6 @@ return var/obj/item/multitool/M = I M.set_multitool_buffer(user, src) + +/obj/machinery/clonescanner/force_eject_occupant(mob/target) + remove_mob() diff --git a/code/game/machinery/computer/brigcells.dm b/code/game/machinery/computer/brigcells.dm index 07a84e492f0..e87afa16c98 100644 --- a/code/game/machinery/computer/brigcells.dm +++ b/code/game/machinery/computer/brigcells.dm @@ -61,7 +61,7 @@ var/obj/machinery/door_timer/T = locate(ref) if(T) T.timer_end() - T.Radio.autosay("Timer stopped manually from a cell management console.", T.name, "Security", list(z)) + T.Radio.autosay("Timer stopped manually from a cell management console.", T.name, "Security") return TRUE return FALSE diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index 97a55c19cb0..40f707866e0 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -645,7 +645,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) if(R.fields["id"] == E.fields["id"]) if(status_valid_for_demotion(R.fields["criminal"])) set_criminal_status(usr, R, SEC_RECORD_STATUS_DEMOTE, reason, scan.assignment) - Radio.autosay("[scan.registered_name] ([scan.assignment]) has set [tempname] ([temprank]) to demote for: [reason]", name, "Command", list(z)) + Radio.autosay("[scan.registered_name] ([scan.assignment]) has set [tempname] ([temprank]) to demote for: [reason]", name, "Command") message_admins("[key_name_admin(usr)] ([scan.assignment]) has set [tempname] ([temprank]) to demote for: \"[reason]\"") log_game("[key_name(usr)] ([scan.assignment]) has set \"[tempname]\" ([temprank]) to demote for: \"[reason]\".") SSjobs.notify_by_name(tempname, "[scan.registered_name] ([scan.assignment]) has ordered your demotion. Report to their office, or the HOP. Reason given: \"[reason]\"") diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index f04445faf6f..fadd07fa124 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -433,7 +433,7 @@ announce.autosay("[occupant.real_name] ([announce_rank]) [on_store_message]", "[on_store_name]") else if(announce_rank) - announce.autosay("[occupant.real_name] ([announce_rank]) [on_store_message]", "[on_store_name]") + announce.autosay("[occupant.real_name] ([announce_rank]) [on_store_message]", "[on_store_name]") else announce.autosay("[occupant.real_name] [on_store_message]", "[on_store_name]") visible_message("[src] hums and hisses as it moves [occupant.real_name] into storage.") @@ -613,6 +613,9 @@ /obj/machinery/cryopod/blob_act() return //Sorta gamey, but we don't really want these to be destroyed. +/obj/machinery/cryopod/force_eject_occupant(mob/target) + go_out() + /obj/machinery/cryopod/offstation // Won't announce when used for cryoing. silent = TRUE @@ -667,7 +670,7 @@ /proc/cryo_ssd(mob/living/person_to_cryo) if(istype(person_to_cryo.loc, /obj/machinery/cryopod)) - return 0 + return FALSE if(isobj(person_to_cryo.loc)) var/obj/O = person_to_cryo.loc O.force_eject_occupant(person_to_cryo) @@ -685,8 +688,8 @@ var/obj/effect/portal/SP = new /obj/effect/portal(T, null, null, 40, create_sparks = FALSE) SP.name = "NT SSD Teleportation Portal" target_cryopod.take_occupant(person_to_cryo, 1) - return 1 - return 0 + return TRUE + return FALSE /proc/force_cryo_human(mob/living/carbon/person_to_cryo) if(!istype(person_to_cryo)) diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index f3e3025c7ab..63b1325a260 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -56,7 +56,7 @@ /obj/structure/barricade/CanPass(atom/movable/mover, turf/target)//So bullets will fly over and stuff. if(locate(/obj/structure/barricade) in get_turf(mover)) return TRUE - else if(istype(mover, /obj/item/projectile)) + else if(isprojectile(mover)) if(!anchored) return TRUE var/obj/item/projectile/proj = mover @@ -449,7 +449,7 @@ /obj/structure/barricade/dropwall/firewall/Crossed(atom/movable/AM, oldloc) . = ..() - if(!istype(AM, /obj/item/projectile)) + if(!isprojectile(AM)) return var/obj/item/projectile/P = AM P.immolate ++ diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index fbc5c3fb08d..9af68c60df5 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -166,7 +166,7 @@ return if(timing) if(timeleft() <= 0) - Radio.autosay("Timer has expired. Releasing prisoner.", name, "Security", list(z)) + Radio.autosay("Timer has expired. Releasing prisoner.", name, "Security") occupant = CELL_NONE timer_end() // open doors, reset timer, clear status screen timing = FALSE @@ -385,7 +385,7 @@ return FALSE releasetime = world.timeofday + timetoset var/resettext = isobserver(usr) ? "for: [reset_reason]." : "by [usr.name] for: [reset_reason]." - Radio.autosay("Prisoner [occupant] had their timer reset [resettext]", name, "Security", list(z)) + Radio.autosay("Prisoner [occupant] had their timer reset [resettext]", name, "Security") notify_prisoner("Your brig timer has been reset for: '[reset_reason]'.") var/datum/data/record/R = find_security_record("name", occupant) if(istype(R)) @@ -396,7 +396,7 @@ if(timing) timer_end() var/stoptext = isobserver(usr) ? "from cell control." : "by [usr.name]." - Radio.autosay("Timer stopped manually [stoptext]", name, "Security", list(z)) + Radio.autosay("Timer stopped manually [stoptext]", name, "Security") else . = FALSE if("flash") diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index e4a3ce3450d..4afbe9da35e 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -93,7 +93,7 @@ /obj/machinery/iv_drip/Move(NewLoc, direct) . = ..() if(!.) // ..() will return 0 if we didn't actually move anywhere. - return . + return playsound(loc, pick('sound/items/cartwheel1.ogg', 'sound/items/cartwheel2.ogg'), 100, 1, ignore_walls = FALSE) #undef IV_TAKING diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index 3ad64115567..4010ba26453 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -547,7 +547,7 @@ if(istype(mover) && mover.checkpass(PASSGLASS)) return prob(20) else - if(istype(mover, /obj/item/projectile)) + if(isprojectile(mover)) return prob(10) else return !density @@ -563,7 +563,7 @@ var/mob/living/M = mover if("syndicate" in M.faction) return TRUE - if(istype(mover, /obj/item/projectile)) + if(isprojectile(mover)) return FALSE return ..(mover, target, height) diff --git a/code/game/machinery/tcomms/tcomms_base.dm b/code/game/machinery/tcomms/tcomms_base.dm index 2517ac6cacd..f89810dd4d8 100644 --- a/code/game/machinery/tcomms/tcomms_base.dm +++ b/code/game/machinery/tcomms/tcomms_base.dm @@ -191,7 +191,7 @@ GLOBAL_LIST_EMPTY(tcomms_machines) /// Origin of the signal var/datum/radio_frequency/connection /// Who sent it - var/mob/sender + var/atom/movable/sender /// The radio it was sent from var/obj/item/radio/radio /// The signal data (See defines/radio.dm) diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm index b72b6a7b714..1b84d8faef3 100644 --- a/code/game/machinery/transformer.dm +++ b/code/game/machinery/transformer.dm @@ -223,7 +223,7 @@ sleep(30) /obj/machinery/transformer/xray/proc/scan_rec(obj/item/I) - if(istype(I, /obj/item/gun)) + if(isgun(I)) return TRUE if(istype(I, /obj/item/transfer_valve)) return TRUE diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index 2513acdddba..979e78469ea 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -233,6 +233,8 @@ chassis.use_power(energy_drain) update_equip_info() +/obj/item/mecha_parts/mecha_equipment/medical/sleeper/force_eject_occupant(mob/target) + go_out() /obj/item/mecha_parts/mecha_equipment/medical/syringe_gun name = "exosuit syringe gun" diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index 08703285cc2..3005942594c 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -47,7 +47,7 @@ if(prob(50)) to_chat(mover, "You get stuck in [src] for a moment.") return FALSE - else if(istype(mover, /obj/item/projectile)) + else if(isprojectile(mover)) return prob(30) return TRUE diff --git a/code/game/objects/items/devices/radio/radio_objects.dm b/code/game/objects/items/devices/radio/radio_objects.dm index 9553c14b5de..a26c5a126fa 100644 --- a/code/game/objects/items/devices/radio/radio_objects.dm +++ b/code/game/objects/items/devices/radio/radio_objects.dm @@ -256,7 +256,7 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems) /obj/item/radio/proc/ToggleReception() listening = !listening && !(wires.is_cut(WIRE_RADIO_RECEIVER) || wires.is_cut(WIRE_RADIO_SIGNAL)) -/obj/item/radio/proc/autosay(message, from, channel, role = "Unknown", follow_target_override) //BS12 EDIT +/obj/item/radio/proc/autosay(message, from, channel, follow_target_override) //BS12 EDIT var/datum/radio_frequency/connection = null if(channel && channels && length(channels) > 0) if(channel == "department") @@ -274,10 +274,6 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems) return if(!connection) return - var/mob/living/automatedannouncer/A = new /mob/living/automatedannouncer(src) - A.name = from - A.role = role - A.message = message var/jammed = FALSE for(var/obj/item/jammer/jammer in GLOB.active_jammers) if(get_dist(get_turf(src), get_turf(jammer)) < jammer.range) @@ -290,7 +286,7 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems) // Make us a message datum! var/datum/tcomms_message/tcm = new tcm.connection = connection - tcm.sender = A + tcm.sender = src tcm.radio = src tcm.sender_name = from tcm.message_pieces = message_pieces @@ -312,29 +308,6 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems) for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines) C.handle_message(tcm) qdel(tcm) // Delete the message datum - qdel(A) - -// Just a dummy mob used for making announcements, so we don't create AIs to do this -// I'm not sure who thought that was a good idea. -- Crazylemon -/mob/living/automatedannouncer - var/role = "" - var/lifetime_timer - var/message = "" - universal_speak = TRUE - -/mob/living/automatedannouncer/New() - lifetime_timer = addtimer(CALLBACK(src, PROC_REF(autocleanup)), 10 SECONDS, TIMER_STOPPABLE) - ..() - -/mob/living/automatedannouncer/Destroy() - if(lifetime_timer) - deltimer(lifetime_timer) - lifetime_timer = null - return ..() - -/mob/living/automatedannouncer/proc/autocleanup() - stack_trace("An announcer somehow managed to outlive the radio! Deleting! (Message: [message])") - qdel(src) // Interprets the message mode when talking into a radio, possibly returning a connection datum /obj/item/radio/proc/handle_message_mode(mob/living/M as mob, list/message_pieces, message_mode) diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index 2e8f73059fd..463a69a18d3 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -75,7 +75,7 @@ /obj/item/taperecorder/attack_hand(mob/user) if(loc == user) if(mytape) - if(user.l_hand != src && user.r_hand != src) + if(!user.is_holding(src)) ..() return eject(user) diff --git a/code/game/objects/items/his_grace.dm b/code/game/objects/items/his_grace.dm index 7766452893d..12d5a908dce 100644 --- a/code/game/objects/items/his_grace.dm +++ b/code/game/objects/items/his_grace.dm @@ -110,7 +110,7 @@ go_rabid() return - if(!(src in list(master.l_hand, master.r_hand))) + if(!master.is_holding(src)) go_rabid() return diff --git a/code/game/objects/items/sport.dm b/code/game/objects/items/sport.dm index a0fe0d7f43b..862cdeecce2 100644 --- a/code/game/objects/items/sport.dm +++ b/code/game/objects/items/sport.dm @@ -46,7 +46,7 @@ . = ..() var/mob/living/carbon/human/M = hit_atom if(ishuman(hit_atom) && (M.wear_suit?.type in suit_types)) - if(M.r_hand == src || M.l_hand == src) + if(M.is_holding(src)) return playsound(src, 'sound/items/dodgeball.ogg', 50, 1) M.KnockDown(6 SECONDS) @@ -86,7 +86,7 @@ return /obj/structure/holohoop/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) - if(isitem(AM) && !istype(AM, /obj/item/projectile)) + if(isitem(AM) && !isprojectile(AM)) if(prob(50) || HAS_TRAIT(throwingdatum.thrower, TRAIT_BADASS)) AM.forceMove(get_turf(src)) visible_message("Swish! [AM] lands in [src].") diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 9e0e5f69d15..49c45f27fe8 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -336,6 +336,7 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( new /datum/stack_recipe("fish bag", /obj/item/storage/bag/fish, 4), new /datum/stack_recipe("mail bag", /obj/item/storage/bag/mail, 4), new /datum/stack_recipe("construction bag", /obj/item/storage/bag/construction, 4), + new /datum/stack_recipe("money bag", /obj/item/storage/bag/money, 3), )), null, new /datum/stack_recipe("improvised gauze", /obj/item/stack/medical/bruise_pack/improvised, 1, 2, 6), diff --git a/code/game/objects/items/weapons/bio_chips/bio_chip_pad.dm b/code/game/objects/items/weapons/bio_chips/bio_chip_pad.dm index 8ddc1d8cfb3..ffb48b26c2b 100644 --- a/code/game/objects/items/weapons/bio_chips/bio_chip_pad.dm +++ b/code/game/objects/items/weapons/bio_chips/bio_chip_pad.dm @@ -45,6 +45,7 @@ C.forceMove(src) case = C update_icon(UPDATE_ICON_STATE) + SStgui.update_uis(src) /obj/item/bio_chip_pad/proc/eject_case(mob/user) if(!case) @@ -53,13 +54,9 @@ if(user.put_in_hands(case)) add_fingerprint(user) case.add_fingerprint(user) - case = null - update_icon(UPDATE_ICON_STATE) - return - - case.forceMove(get_turf(src)) case = null update_icon(UPDATE_ICON_STATE) + SStgui.update_uis(src) /obj/item/bio_chip_pad/AltClick(mob/user) if(user.stat || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED) || !Adjacent(user)) @@ -74,6 +71,7 @@ ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "BioChipPad", name) + ui.set_autoupdate(FALSE) ui.open() /obj/item/bio_chip_pad/ui_data(mob/user) @@ -97,7 +95,7 @@ /obj/item/bio_chip_pad/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) if(..()) return - + . = TRUE switch(action) if("eject_case") eject_case(ui.user) diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm index a16963b648a..67bc3f4994e 100644 --- a/code/game/objects/items/weapons/flamethrower.dm +++ b/code/game/objects/items/weapons/flamethrower.dm @@ -42,7 +42,7 @@ var/turf/location = loc if(ismob(location)) var/mob/M = location - if(M.l_hand == src || M.r_hand == src) + if(M.is_holding(src)) location = M.loc if(isturf(location)) //start a fire if possible igniter.flamethrower_process(location) diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm index 0cf30e2db5e..a117746c570 100644 --- a/code/game/objects/items/weapons/holy_weapons.dm +++ b/code/game/objects/items/weapons/holy_weapons.dm @@ -360,7 +360,7 @@ if(ishuman(loc)) var/mob/living/carbon/human/our_location = loc if(istype(our_location)) - if(src != our_location.l_hand && src != our_location.r_hand) + if(!our_location.is_holding(src)) return if(our_location.Adjacent(attacking_atom)) // with a buddy we deal 12 damage :D our_location.do_attack_animation(attacking_atom, used_item = src) diff --git a/code/game/objects/items/weapons/melee/energy_melee_weapons.dm b/code/game/objects/items/weapons/melee/energy_melee_weapons.dm index 22acf04add8..0313f5ae46a 100644 --- a/code/game/objects/items/weapons/melee/energy_melee_weapons.dm +++ b/code/game/objects/items/weapons/melee/energy_melee_weapons.dm @@ -240,7 +240,7 @@ . = ..() if(!.) // they did not block the attack return - if(istype(hitby, /obj/item/projectile)) + if(isprojectile(hitby)) var/obj/item/projectile/P = hitby if(P.reflectability == REFLECTABILITY_NEVER) //only 1 magic spell does this, but hey, needed owner.visible_message("[owner] blocks [attack_text] with [src]!") diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm index e2d1b0fe3c7..398b6c4d4ed 100644 --- a/code/game/objects/items/weapons/shields.dm +++ b/code/game/objects/items/weapons/shields.dm @@ -86,7 +86,7 @@ return /obj/item/shield/energy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(istype(hitby, /obj/item/projectile)) + if(isprojectile(hitby)) var/obj/item/projectile/P = hitby if(P.shield_buster && active) toggle(owner, TRUE) diff --git a/code/game/objects/items/weapons/storage/briefcase.dm b/code/game/objects/items/weapons/storage/briefcase.dm index ed9a96a2b93..77cc3c0f361 100644 --- a/code/game/objects/items/weapons/storage/briefcase.dm +++ b/code/game/objects/items/weapons/storage/briefcase.dm @@ -43,7 +43,7 @@ /obj/item/storage/briefcase/false_bottomed/afterattack(atom/A, mob/user, flag, params) ..() - if(stored_item && istype(stored_item, /obj/item/gun) && !Adjacent(A)) + if(stored_item && isgun(stored_item) && !Adjacent(A)) var/obj/item/gun/stored_gun = stored_item stored_gun.afterattack(A, user, flag, params) diff --git a/code/game/objects/structures/fence.dm b/code/game/objects/structures/fence.dm index e544227d383..1a2535814c0 100644 --- a/code/game/objects/structures/fence.dm +++ b/code/game/objects/structures/fence.dm @@ -61,7 +61,7 @@ /obj/structure/fence/CanPass(atom/movable/mover, turf/target) if(istype(mover) && mover.checkpass(PASSFENCE)) return TRUE - if(istype(mover, /obj/item/projectile)) + if(isprojectile(mover)) return TRUE if(!density) return TRUE diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 6585976999e..1c0bc9cd224 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -410,7 +410,7 @@ if(istype(mover) && mover.checkpass(PASSGRILLE)) return prob(girderpasschance) else - if(istype(mover, /obj/item/projectile)) + if(isprojectile(mover)) return prob(girderpasschance) else return 0 diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index fbc538af4a1..4097219ef38 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -123,7 +123,7 @@ return TRUE if(istype(mover) && mover.checkpass(PASSGRILLE)) return TRUE - if(istype(mover, /obj/item/projectile)) + if(isprojectile(mover)) return (prob(30) || !density) /obj/structure/grille/CanPathfindPass(obj/item/card/id/ID, dir, caller, no_id = FALSE) diff --git a/code/game/objects/structures/railings.dm b/code/game/objects/structures/railings.dm index ff67ffde85a..5acfde9058a 100644 --- a/code/game/objects/structures/railings.dm +++ b/code/game/objects/structures/railings.dm @@ -102,7 +102,7 @@ /obj/structure/railing/CanPass(atom/movable/mover, turf/target) if(istype(mover) && mover.checkpass(PASSFENCE)) return TRUE - if(istype(mover, /obj/item/projectile)) + if(isprojectile(mover)) return TRUE if(ismob(mover)) var/mob/living/M = mover @@ -130,7 +130,7 @@ var/mob/living/M = O if(istype(O) && O.checkpass(PASSFENCE)) return TRUE - if(istype(O, /obj/item/projectile)) + if(isprojectile(O)) return TRUE if(istype(M)) if(M.flying || M.floating || (IS_HORIZONTAL(M) && HAS_TRAIT(M, TRAIT_CONTORTED_BODY))) diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 950a932c405..6671d35a935 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -799,10 +799,10 @@ . = ..() if(!.) // ..() will return 0 if we didn't actually move anywhere. - return . + return if(direct & (direct - 1)) // This represents a diagonal movement, which is split into multiple cardinal movements. We'll handle moving the items on the cardinals only. - return . + return playsound(loc, pick('sound/items/cartwheel1.ogg', 'sound/items/cartwheel2.ogg'), 100, 1, ignore_walls = FALSE) diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index 48549b082d6..06adebfaa0e 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -207,7 +207,7 @@ if(log_info) INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(log_connection), ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_BANNED) qdel(query) - return . + return qdel(query) . = ..() //default pager ban stuff @@ -224,4 +224,3 @@ log_adminwarn("Failed Login: [key] [computer_id] [address] - Banned [.["message"]]") if(log_info) INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(log_connection), ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_BANNED) - return . diff --git a/code/modules/admin/misc_admin_procs.dm b/code/modules/admin/misc_admin_procs.dm index 40729ea7e0f..03aa0b49fb0 100644 --- a/code/modules/admin/misc_admin_procs.dm +++ b/code/modules/admin/misc_admin_procs.dm @@ -613,6 +613,7 @@ GLOBAL_VAR_INIT(nologevent, 0) log_admin("[key_name(usr)] delayed the game.") else SSticker.ticker_going = TRUE + SSticker.round_start_time = world.time + SSticker.pregame_timeleft to_chat(world, "The game will start soon.") log_admin("[key_name(usr)] removed the delay.") diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 6d8ad148178..852168cb285 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -187,17 +187,18 @@ else receive_message = chat_box_ahelp(receive_message) to_chat(C, receive_message) - var/send_window_link = "(WINDOW)" - if(message_type == MESSAGE_TYPE_MENTORPM && check_rights(R_ADMIN|R_MENTOR, 0, mob)) - send_window_link = ticket_link - else if(message_type == MESSAGE_TYPE_ADMINPM && check_rights(R_ADMIN, 0, mob)) - send_window_link = ticket_link - var/send_message = "[send_pm_type][type] to-[holder ? key_name(C, TRUE, type, ticket_id = ticket_id) : key_name_hidden(C, TRUE, type, ticket_id = ticket_id)]:

[emoji_msg]

[ping_link] [send_window_link] [alert_link]" - if(message_type == MESSAGE_TYPE_MENTORPM) - send_message = chat_box_mhelp(send_message) - else - send_message = chat_box_ahelp(send_message) - to_chat(src, send_message) + if(C != src) + var/send_window_link = "(WINDOW)" + if(message_type == MESSAGE_TYPE_MENTORPM && check_rights(R_ADMIN|R_MENTOR, 0, mob)) + send_window_link = ticket_link + else if(message_type == MESSAGE_TYPE_ADMINPM && check_rights(R_ADMIN, 0, mob)) + send_window_link = ticket_link + var/send_message = "[send_pm_type][type] to-[holder ? key_name(C, TRUE, type, ticket_id = ticket_id) : key_name_hidden(C, TRUE, type, ticket_id = ticket_id)]:

[emoji_msg]

[ping_link] [send_window_link] [alert_link]" + if(message_type == MESSAGE_TYPE_MENTORPM) + send_message = chat_box_mhelp(send_message) + else + send_message = chat_box_ahelp(send_message) + to_chat(src, send_message) var/third_party_message if(message_type == MESSAGE_TYPE_MENTORPM) diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 6e3753a705c..47529556d96 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -989,3 +989,24 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) vis.set_content(ui_dat.Join("")) vis.open(FALSE) + +/client/proc/cmd_clean_radiation() + set name = "Remove All Radiation" + set desc = "Remove all radiation in the world." + set category = "Debug" + + if(!check_rights(R_DEBUG)) + return + + if(alert(src, "Are you sure you want to remove all radiation in the world? This may lag the server. Alternatively, use the radiation cleaning buildmode.", "Lag warning", "Yes, I'm sure", "No, I want to live") != "Yes, I'm sure") + return + + log_and_message_admins("is decontaminating the world of all radiation. (This may be laggy!)") + + var/counter = 0 + for(var/datum/component/radioactive/rad as anything in SSradiation.all_radiations) + rad.admin_decontaminate() + counter++ + CHECK_TICK + + log_and_message_admins_no_usr("The world has been decontaminated of [counter] radiation components.") diff --git a/code/modules/admin/verbs/freeze.dm b/code/modules/admin/verbs/freeze.dm index 00f68307136..988c2df44b2 100644 --- a/code/modules/admin/verbs/freeze.dm +++ b/code/modules/admin/verbs/freeze.dm @@ -93,12 +93,12 @@ GLOBAL_LIST_EMPTY(frozen_atom_list) // A list of admin-frozen atoms. /obj/machinery/atmospherics/supermatter_crystal/admin_Freeze(client/admin) var/obj/effect/overlay/adminoverlay/freeze_overlay = new if(processes) - radio.autosay("Alert: Unknown intervention has frozen causality around the crystal. It is not progressing in local timespace.", name, "Engineering", list(z)) + radio.autosay("Alert: Unknown intervention has frozen causality around the crystal. It is not progressing in local timespace.", name, "Engineering") GLOB.frozen_atom_list += src processes = FALSE add_overlay(freeze_overlay) else - radio.autosay("Alert: Unknown intervention has ceased around the crystal. It has returned to the regular flow of time.", name, "Engineering", list(z)) + radio.autosay("Alert: Unknown intervention has ceased around the crystal. It has returned to the regular flow of time.", name, "Engineering") GLOB.frozen_atom_list -= src processes = TRUE cut_overlay(freeze_overlay) diff --git a/code/modules/admin/verbs/toggledebugverbs.dm b/code/modules/admin/verbs/toggledebugverbs.dm index 74d8358640c..120a69b924b 100644 --- a/code/modules/admin/verbs/toggledebugverbs.dm +++ b/code/modules/admin/verbs/toggledebugverbs.dm @@ -16,6 +16,7 @@ GLOBAL_LIST_INIT(admin_verbs_show_debug_verbs, list( /client/proc/forceEvent, /client/proc/admin_redo_space_transitions, /client/proc/make_turf_space_map, + /client/proc/cmd_clean_radiation, )) // Would be nice to make this a permanent admin pref so we don't need to click it each time diff --git a/code/modules/buildmode/submodes/antirad_mode.dm b/code/modules/buildmode/submodes/antirad_mode.dm new file mode 100644 index 00000000000..1ddd9964bb0 --- /dev/null +++ b/code/modules/buildmode/submodes/antirad_mode.dm @@ -0,0 +1,55 @@ +/datum/buildmode_mode/clean_radiation + key = "rad" + +/datum/buildmode_mode/clean_radiation/show_help(mob/user) + var/list/messages = list( + "***********************************************************", + "Left Mouse Button on obj/turf/mob = Remove radiation of selected target.", + "Ctrl-Left Mouse Button on screen = Remove all radiation in your sight.", + "Right Mouse Button on obj/turf/mob = Deep clean: Remove radiation of all recursive contents of turf.", + "Ctrl-Right Mouse Button on screen = Deep clean: Remove radiation of all recursive contents in your sight.", + "***********************************************************" + ) + to_chat(user, messages.Join("
")) + +/datum/buildmode_mode/clean_radiation/handle_click(mob/user, params, atom/target) + var/list/pa = params2list(params) + var/deep_clean = pa.Find("right") + var/clean_screen = pa.Find("ctrl") + + if(!clean_screen) + if(!deep_clean) + if(SEND_SIGNAL(target, COMSIG_ADMIN_DECONTAMINATE)) + to_chat(user, "Decontaminated [target].") + log_admin("Build Mode: [key_name(user)] decontaminated radiation at ([target.x],[target.y],[target.z])") + return + + var/counter = 0 + var/turf/T = get_turf(target) + counter += SEND_SIGNAL(T, COMSIG_ADMIN_DECONTAMINATE) + for(var/atom/movable/cleanable in T) + counter += SEND_SIGNAL(cleanable, COMSIG_ADMIN_DECONTAMINATE) + CHECK_TICK + + if(isliving(cleanable)) + var/mob/living/L = cleanable + for(var/atom/movable/cleanable2 in L.get_contents()) + counter += SEND_SIGNAL(cleanable2, COMSIG_ADMIN_DECONTAMINATE) + CHECK_TICK + to_chat(user, "Decontaminated [counter] atom\s.") + log_admin("Build Mode: [key_name(user)] deep-clean decontaminated radiation at ([target.x],[target.y],[target.z])") + return + + var/counter = 0 + for(var/turf/T in range(user.client.view, user)) + counter += SEND_SIGNAL(T, COMSIG_ADMIN_DECONTAMINATE) + for(var/atom/movable/cleanable in T) + counter += SEND_SIGNAL(cleanable, COMSIG_ADMIN_DECONTAMINATE) + CHECK_TICK + if(deep_clean && isliving(cleanable)) + var/mob/living/L = cleanable + for(var/atom/movable/cleanable2 in L.get_contents()) + counter += SEND_SIGNAL(cleanable2, COMSIG_ADMIN_DECONTAMINATE) + CHECK_TICK + to_chat(user, "Decontaminated [counter] atom\s.") + log_admin("Build Mode: [key_name(user)] [deep_clean ? "deep-clean " : ""]decontaminated their screen of radiation at ([target.x],[target.y],[target.z])") diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index aa06fa2055c..d47f82b5e02 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -62,6 +62,9 @@ var/datum/click_intercept/click_intercept = null + /// Time when the click was intercepted + var/click_intercept_time = 0 + //datum that controls the displaying and hiding of tooltips var/datum/tooltip/tooltips @@ -132,6 +135,27 @@ var/list/active_keybindings = list() /// The client's movement keybindings to directions, which work regardless of modifiers. var/list/movement_kb_dirs = list() + + /// Used to make a special mouse cursor, this one for mouse up icon + var/mouse_up_icon = null + /// Used to make a special mouse cursor, this one for mouse up icon + var/mouse_down_icon = null + /// Used to override the mouse cursor so it doesnt get reset + var/mouse_override_icon = null + + /// Autoclick list of two elements, first being the clicked thing, second being the parameters. + var/list/atom/selected_target[2] + /// Used in MouseDrag to preserve the original mouse click parameters + var/mouseParams = "" + /// Used in MouseDrag to preserve the last mouse-entered location. + var/mouse_location_UID + /// Used in MouseDrag to preserve the last mouse-entered object. + var/mouse_object_UID + /// When we started the currently active drag + var/drag_start = 0 + /// The params we passed at the start of the drag, in list form + var/list/drag_details + /// The client's currently moused over datum, limited to movable and stored as UID var/atom/movable/moused_over diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index f21c1b3fbc3..9cc9981ea28 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -75,7 +75,7 @@ var/turf/location = loc if(ismob(location)) var/mob/living/carbon/human/M = location - if(M.l_hand == src || M.r_hand == src || M.head == src) + if(M.is_holding(src) || M.head == src) location = M.loc if(isturf(location)) diff --git a/code/modules/clothing/suits/armor_suits.dm b/code/modules/clothing/suits/armor_suits.dm index 9a5dda61757..f57c9fecf16 100644 --- a/code/modules/clothing/suits/armor_suits.dm +++ b/code/modules/clothing/suits/armor_suits.dm @@ -476,7 +476,7 @@ /obj/item/clothing/suit/armor/reactive/proc/reaction_check(hitby) if(prob(hit_reaction_chance)) - if(istype(hitby, /obj/item/projectile)) + if(isprojectile(hitby)) var/obj/item/projectile/P = hitby if(istype(P, /obj/item/projectile/ion)) return FALSE diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm index 19cc8dbd095..3b7effb8727 100644 --- a/code/modules/clothing/under/accessories/accessory.dm +++ b/code/modules/clothing/under/accessories/accessory.dm @@ -231,7 +231,7 @@ return if(!is_station_level(user.z)) return - GLOB.global_announcer.autosay("[H] has been rewarded [src] by [user]!", "Medal Announcer", channel = channel, follow_target_override = src) + GLOB.global_announcer.autosay("[H] has been rewarded [src] by [user]!", "Medal Announcer", channel, src) channel = null // GOLD (awarded by centcom) diff --git a/code/modules/clothing/under/accessories/holster.dm b/code/modules/clothing/under/accessories/holster.dm index ac798acda90..e31e66f186a 100644 --- a/code/modules/clothing/under/accessories/holster.dm +++ b/code/modules/clothing/under/accessories/holster.dm @@ -36,7 +36,7 @@ to_chat(user, "There is already a [holstered] holstered here!") return - if(!istype(I, /obj/item/gun)) + if(!isgun(I)) to_chat(user, "Only guns can be holstered!") return diff --git a/code/modules/events/blob/theblob.dm b/code/modules/events/blob/theblob.dm index c8d6f3da473..727eb3354ca 100644 --- a/code/modules/events/blob/theblob.dm +++ b/code/modules/events/blob/theblob.dm @@ -70,6 +70,11 @@ GLOBAL_LIST_EMPTY(blob_minions) /obj/structure/blob/blob_act(obj/structure/blob/B) return +/obj/structure/blob/bullet_act(obj/item/projectile/P) + if(istype(P, /obj/item/projectile/kinetic)) + P.damage /= 2 + return ..() + /obj/structure/blob/proc/Life() return diff --git a/code/modules/food_and_drinks/drinks/drinks/cans.dm b/code/modules/food_and_drinks/drinks/drinks/cans.dm index c98487ba69c..e797c5ef7b6 100644 --- a/code/modules/food_and_drinks/drinks/drinks/cans.dm +++ b/code/modules/food_and_drinks/drinks/drinks/cans.dm @@ -49,7 +49,7 @@ if(can_opened) to_chat(H, "You can't shake up an already opened drink!") return - if(src == H.l_hand || src == H.r_hand) + if(H.is_holding(src)) can_shake = FALSE addtimer(CALLBACK(src, PROC_REF(reset_shakable)), 1 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE) to_chat(H, "You start shaking up [src].") diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm index 5896e70e42d..51a0d347356 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm @@ -321,7 +321,8 @@ operating = FALSE update_icon(UPDATE_OVERLAYS | UPDATE_ICON_STATE) - +/obj/machinery/gibber/force_eject_occupant(mob/target) + go_out() /* AUTOGIBBER */ diff --git a/code/modules/hydroponics/gene_modder.dm b/code/modules/hydroponics/gene_modder.dm index 2965904de88..2662b6e68cd 100644 --- a/code/modules/hydroponics/gene_modder.dm +++ b/code/modules/hydroponics/gene_modder.dm @@ -171,6 +171,7 @@ ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "GeneModder", name) + ui.set_autoupdate(FALSE) ui.open() /obj/machinery/plantgenes/ui_data(mob/user) diff --git a/code/modules/hydroponics/seed_extractor.dm b/code/modules/hydroponics/seed_extractor.dm index a2710f815b2..37ac3e36132 100644 --- a/code/modules/hydroponics/seed_extractor.dm +++ b/code/modules/hydroponics/seed_extractor.dm @@ -96,6 +96,7 @@ if(loaded) to_chat(user, "You transfer [loaded] seeds from [O] into [src].") + SStgui.update_uis(src) else var/seedable = 0 for(var/obj/item/food/snacks/grown/ignored in P) @@ -115,10 +116,10 @@ else if(istype(O, /obj/item/unsorted_seeds)) to_chat(user, "You need to sort [O] first!") return ..() - else if(istype(O,/obj/item/seeds)) - if(add_seed(O, user)) - to_chat(user, "You add [O] to [name].") - updateUsrDialog() + else if(istype(O, /obj/item/seeds)) + add_seed(O, user) + to_chat(user, "You add [O] to [name].") + SStgui.update_uis(src) return else if(seedify(O,-1, src, user)) to_chat(user, "You extract some seeds.") @@ -143,6 +144,7 @@ ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "SeedExtractor", name) + ui.set_autoupdate(FALSE) ui.open() /obj/machinery/seed_extractor/ui_data(mob/user) @@ -177,18 +179,14 @@ /obj/machinery/seed_extractor/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) if(..()) return - . = FALSE + . = TRUE switch(action) if("vend") vend_seed(params["seed_id"], params["seed_variant"], params["vend_amount"]) add_fingerprint(usr) - . = TRUE if("set_vend_amount") - if(!length(params["vend_amount"])) - return vend_amount = clamp(params["vend_amount"], 1, MAX_DISPENSE_SEEDS) add_fingerprint(usr) - . = TRUE /obj/machinery/seed_extractor/proc/vend_seed(seed_id, seed_variant, amount) if(!seed_id) @@ -241,7 +239,6 @@ pile_count++ piles += new_pile O.forceMove(src) - return /datum/seed_pile var/path diff --git a/code/modules/mining/lavaland/loot/tendril_loot.dm b/code/modules/mining/lavaland/loot/tendril_loot.dm index fc5a2570944..2055b5e736a 100644 --- a/code/modules/mining/lavaland/loot/tendril_loot.dm +++ b/code/modules/mining/lavaland/loot/tendril_loot.dm @@ -57,7 +57,7 @@ /obj/item/shared_storage/attack_self(mob/living/carbon/user) if(!iscarbon(user)) return - if(src == user.l_hand || src == user.r_hand) + if(user.is_holding(src)) bag?.open(user) else ..() diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index bf9bfc53edf..65386ffc6de 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -223,7 +223,7 @@ /obj/item/clothing/head/hooded/berserker/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) if(berserk_active) return - if(istype(hitby, /obj/item/projectile)) + if(isprojectile(hitby)) var/obj/item/projectile/P = hitby if(P.damage_type == STAMINA) return //no disabler rage diff --git a/code/modules/mining/mint.dm b/code/modules/mining/mint.dm index bbaf8aa8e72..5ff52401eff 100644 --- a/code/modules/mining/mint.dm +++ b/code/modules/mining/mint.dm @@ -1,116 +1,193 @@ -/**********************Mint**************************/ - +#define COIN_COST MINERAL_MATERIAL_AMOUNT * 0.2 /obj/machinery/mineral/mint name = "coin press" icon = 'icons/obj/economy.dmi' - icon_state = "coinpress0" + icon_state = "coin_press" density = TRUE anchored = TRUE - var/newCoins = 0 //how many coins the machine made in it's last load - var/processing = FALSE - var/chosen = MAT_METAL //which material will be used to make coins - var/coinsToProduce = 10 - speed_process = TRUE - + /// How many coins did the machine make in total. + var/total_coins = 0 + /// Is it creating coins now? + var/active = FALSE + /// Which material will be used to make coins or for ejecting. + var/chosen_material + /// Inserted money bag. + var/obj/item/storage/bag/money/money_bag /obj/machinery/mineral/mint/Initialize(mapload) . = ..() - AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_URANIUM, MAT_DIAMOND, MAT_BANANIUM, MAT_TRANQUILLITE), MINERAL_MATERIAL_AMOUNT * 50, FALSE, /obj/item/stack) + var/static/list/coin_materials = list() + if(!length(coin_materials)) + for(var/datum/material/coin_mat as anything in subtypesof(/datum/material)) + var/obj/item/coin/coin_type = coin_mat.coin_type + if(!coin_type) + continue + coin_materials += coin_mat.id + + AddComponent(/datum/component/material_container, coin_materials, MINERAL_MATERIAL_AMOUNT * 50, FALSE, /obj/item/stack, _after_insert = CALLBACK(src, PROC_REF(material_insert))) + chosen_material = pick(coin_materials[1]) + +/obj/machinery/mineral/mint/Destroy() + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + materials.retrieve_all() + return ..() + +/obj/machinery/mineral/mint/update_icon_state() + if(active) + icon_state = "coin_press-active" + else + icon_state = "coin_press" /obj/machinery/mineral/mint/wrench_act(mob/user, obj/item/I) default_unfasten_wrench(user, I, time = 4 SECONDS) return TRUE -/obj/machinery/mineral/mint/process() - var/turf/T = get_step(src, input_dir) - if(!T) - return - - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - for(var/obj/item/stack/sheet/O in T) - materials.insert_stack(O, O.amount) - /obj/machinery/mineral/mint/attack_hand(mob/user) - if(..()) - return - var/dat = "Coin Press
" + add_fingerprint(user) + ui_interact(user) + +/obj/machinery/mineral/mint/attack_ghost(mob/user) + ui_interact(user) + +/obj/machinery/mineral/mint/ui_state(mob/user) + return GLOB.default_state + +/obj/machinery/mineral/mint/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "CoinMint", name) + ui.set_autoupdate(FALSE) + ui.open() + +/obj/machinery/mineral/mint/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/materials) + ) + +/obj/machinery/mineral/mint/ui_data(mob/user) + var/list/data = list() + + data["active"] = active + data["chosenMaterial"] = chosen_material + data["totalCoins"] = total_coins + data["moneyBag"] = !!money_bag + + if(money_bag) + data["moneyBagContent"] = length(money_bag.contents) + data["moneyBagMaxContent"] = money_bag.storage_slots var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + data["totalMaterials"] = materials.total_amount + data["maxMaterials"] = materials.max_amount + + var/list/material_list = list() for(var/mat_id in materials.materials) - var/datum/material/M = materials.materials[mat_id] - if(!M.amount && chosen != mat_id) - continue - dat += "
[M.name] amount: [M.amount] cm3 " - if(chosen == mat_id) - dat += "Chosen" - else - dat += "Choose" + var/datum/material/material = materials.materials[mat_id] + material_list += list(list( + "name" = material.name, + "amount" = material.amount / MINERAL_MATERIAL_AMOUNT, + "id" = material.id + )) + data["materials"] = material_list - var/datum/material/M = materials.materials[chosen] + return data - dat += "

Will produce [coinsToProduce] [lowertext(M.name)] coins if enough materials are available.
" - dat += "-10 " - dat += "-5 " - dat += "-1 " - dat += "+1 " - dat += "+5 " - dat += "+10 " - - dat += "

In total this machine produced [newCoins] coins." - dat += "
Make coins" - user << browse(dat, "window=mint") - -/obj/machinery/mineral/mint/Topic(href, href_list) +/obj/machinery/mineral/mint/ui_act(action, params, datum/tgui/ui) if(..()) return - usr.set_machine(src) - add_fingerprint(usr) - if(processing) - to_chat(usr, "The machine is processing.") - return + . = TRUE + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - if(href_list["choose"]) - if(materials.materials[href_list["choose"]]) - chosen = href_list["choose"] - if(href_list["chooseAmt"]) - coinsToProduce = clamp(coinsToProduce + text2num(href_list["chooseAmt"]), 0, 1000) - if(href_list["makeCoins"]) - var/temp_coins = coinsToProduce - processing = TRUE - icon_state = "coinpress1" - var/coin_mat = MINERAL_MATERIAL_AMOUNT * 0.2 - var/datum/material/M = materials.materials[chosen] - if(!M || !M.coin_type) - updateUsrDialog() + switch(action) + if("selectMaterial") + if(!materials.materials[params["material"]]) + return + chosen_material = params["material"] + if("activate") + if(active) + active = FALSE + else + try_make_coins() + update_icon(UPDATE_ICON_STATE) + if("ejectMat") + var/datum/material/material = materials.materials[chosen_material] + if(material.amount < MINERAL_MATERIAL_AMOUNT) + to_chat(usr, "Not enough [material.name] to eject!") + return + var/num_sheets = tgui_input_number(usr, "How many sheets do you want to eject?", "Ejecting [material.name]", max_value = round(material.amount / MINERAL_MATERIAL_AMOUNT), min_value = 1) + if(isnull(num_sheets)) + return + materials.retrieve_sheets(num_sheets, chosen_material) + if("ejectBag") + eject_bag(usr) + +/obj/machinery/mineral/mint/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/storage/bag/money)) + if(money_bag) + to_chat(user, "There is already a [money_bag.name] inside!") return + if(!user.drop_item()) + return + to_chat(user, "You put a [I.name] into a [src].") + I.forceMove(src) + money_bag = I + SStgui.update_uis(src) + return - while(coinsToProduce > 0 && materials.can_use_amount(coin_mat, chosen)) - if(!create_coins(M.coin_type)) - visible_message("[src] stops printing to prevent an overflow.") - break - materials.use_amount_type(coin_mat, chosen) - coinsToProduce-- - newCoins++ - updateUsrDialog() - sleep(5) + return ..() - icon_state = "coinpress0" - processing = FALSE - coinsToProduce = temp_coins - updateUsrDialog() +/obj/machinery/mineral/mint/process() + if(!active) + return + if(length(money_bag.contents) >= money_bag.storage_slots) + active = FALSE + visible_message("[src] stops printing to prevent an overflow.") + update_icon(UPDATE_ICON_STATE) + SStgui.update_uis(src) + return -/obj/machinery/mineral/mint/proc/create_coins(P) - var/turf/T = get_step(src,output_dir) - if(!T) - return FALSE - var/obj/item/O = new P(src) - var/obj/item/storage/bag/money/M = locate(/obj/item/storage/bag/money, T) - if(!M) - M = new /obj/item/storage/bag/money(src) - unload_mineral(M) - else if(!M.can_be_inserted(O, FALSE)) // First coin will always fit. But will the Xth? - qdel(O) - return FALSE - O.forceMove(M) - return TRUE + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + var/datum/material/material = materials.materials[chosen_material] + if(!materials.can_use_amount(COIN_COST, chosen_material)) + active = FALSE + visible_message("[src] ceased production due to a lack of material.") + update_icon(UPDATE_ICON_STATE) + SStgui.update_uis(src) + return + + materials.use_amount_type(COIN_COST, chosen_material) + new material.coin_type(money_bag) + total_coins++ + SStgui.update_uis(src) + +/obj/machinery/mineral/mint/proc/try_make_coins(mob/user) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + if(!money_bag) + visible_message("[src] cannot work without a money bag!") + return + if(length(money_bag.contents) == money_bag.storage_slots) + visible_message("[money_bag.name] is full!") + return + if(!materials.can_use_amount(COIN_COST, chosen_material)) + visible_message("Lack of selected material for production!") + return + active = TRUE + +/obj/machinery/mineral/mint/proc/eject_bag(mob/user) + if(!money_bag || !(user && iscarbon(user) && user.Adjacent(src))) + return + if(active) + active = FALSE + if(user.put_in_hands(money_bag)) + to_chat(user, "You take a [money_bag.name] out of [src].") + else + var/turf/T = get_step(src, output_dir) + money_bag.forceMove(T) + money_bag = null + SStgui.update_uis(src) + +/obj/machinery/mineral/mint/proc/material_insert() + SStgui.update_uis(src) + +#undef COIN_COST diff --git a/code/modules/mining/money_bag.dm b/code/modules/mining/money_bag.dm index a626ff933b7..cfe03086e7d 100644 --- a/code/modules/mining/money_bag.dm +++ b/code/modules/mining/money_bag.dm @@ -1,5 +1,3 @@ -/*****************************Money bag********************************/ - /obj/item/storage/bag/money name = "money bag" icon_state = "moneybag" @@ -9,8 +7,8 @@ max_integrity = 100 w_class = WEIGHT_CLASS_BULKY max_w_class = WEIGHT_CLASS_NORMAL - storage_slots = 40 - max_combined_w_class = 40 + storage_slots = 50 + max_combined_w_class = 50 can_hold = list(/obj/item/coin, /obj/item/stack/spacecash) /obj/item/storage/bag/money/vault/populate_contents() diff --git a/code/modules/mob/dead/observer/observer_say.dm b/code/modules/mob/dead/observer/observer_say.dm index 3b97ab5d834..0f86ba90898 100644 --- a/code/modules/mob/dead/observer/observer_say.dm +++ b/code/modules/mob/dead/observer/observer_say.dm @@ -9,19 +9,18 @@ return say_dead(message) -/mob/dead/observer/handle_track(message, verb = "says", mob/speaker = null, speaker_name, atom/follow_target, hard_to_hear) +/mob/dead/observer/handle_track(message, verb = "says", atom/movable/speaker = null, speaker_name, atom/follow_target, hard_to_hear) return "[speaker_name] ([ghost_follow_link(follow_target, ghost=src)])" -/mob/dead/observer/handle_speaker_name(mob/speaker = null, vname, hard_to_hear, check_name_against) +/mob/dead/observer/handle_speaker_name(atom/movable/speaker = null, vname, hard_to_hear, check_name_against) var/speaker_name = ..() - if(!speaker) + if(!speaker || !ismob(speaker)) return speaker_name - //Announce computer and various stuff that broadcasts doesn't use it's real name but AI's can't pretend to be other mobs. - if(isAI(speaker) || isAutoAnnouncer(speaker)) + var/mob/speaker_mob = speaker + if(isAI(speaker_mob)) + //AI's can't pretend to be other mobs. return speaker_name - if(!check_name_against) - check_name_against = speaker_name - if(check_name_against == speaker.real_name) + if(!check_name_against || check_name_against == speaker_mob.real_name) return speaker_name - speaker_name = "[speaker.real_name] ([speaker_name])" + speaker_name = "[speaker_mob.real_name] ([speaker_name])" return speaker_name diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm index b8d064d5d0c..f5f6e0e1ec1 100644 --- a/code/modules/mob/hear_say.dm +++ b/code/modules/mob/hear_say.dm @@ -1,6 +1,6 @@ // At minimum every mob has a hear_say proc. -/mob/proc/combine_message(list/message_pieces, verb, mob/speaker, always_stars = FALSE) +/mob/proc/combine_message(list/message_pieces, verb, atom/movable/speaker, always_stars = FALSE) var/iteration_count = 0 var/msg = "" // This is to make sure that the pieces have actually added something for(var/datum/multilingual_say_piece/SP in message_pieces) @@ -128,7 +128,7 @@ playsound_local(source, speech_sound, sound_vol, 1, sound_frequency) -/mob/proc/hear_radio(list/message_pieces, verb = "says", part_a, part_b, mob/speaker = null, hard_to_hear = 0, vname = "", atom/follow_target, check_name_against) +/mob/proc/hear_radio(list/message_pieces, verb = "says", part_a, part_b, atom/movable/speaker = null, hard_to_hear = 0, vname = "", atom/follow_target, check_name_against) if(!client) return @@ -155,7 +155,7 @@ else to_chat(src, "[part_a][speaker_name][part_b][message]
") -/mob/proc/handle_speaker_name(mob/speaker = null, vname, hard_to_hear) +/mob/proc/handle_speaker_name(atom/movable/speaker = null, vname, hard_to_hear) var/speaker_name = "unknown" if(speaker) speaker_name = speaker.name @@ -168,7 +168,7 @@ return speaker_name -/mob/proc/handle_track(message, verb = "says", mob/speaker = null, speaker_name, atom/follow_target, hard_to_hear) +/mob/proc/handle_track(message, verb = "says", atom/movable/speaker = null, speaker_name, atom/follow_target, hard_to_hear) return /mob/proc/hear_sleep(message) @@ -192,7 +192,7 @@ to_chat(src, heard) -/mob/proc/hear_holopad_talk(list/message_pieces, verb = "says", mob/speaker = null, obj/effect/overlay/holo_pad_hologram/H) +/mob/proc/hear_holopad_talk(list/message_pieces, verb = "says", atom/movable/speaker = null, obj/effect/overlay/holo_pad_hologram/H) if(stat == UNCONSCIOUS) hear_sleep(multilingual_to_message(message_pieces)) return @@ -204,8 +204,9 @@ var/message_unverbed = combine_message(message_pieces, null, speaker) var/name = speaker.name - if(!say_understands(speaker)) - name = speaker.voice_name + if(!say_understands(speaker) && ismob(speaker)) + var/mob/speaker_mob = speaker + name = speaker_mob.voice_name if((client?.prefs.toggles2 & PREFTOGGLE_2_RUNECHAT) && can_hear()) create_chat_message(H, message_unverbed) diff --git a/code/modules/mob/living/brain/living_brain.dm b/code/modules/mob/living/brain/living_brain.dm index 46a63baf1b8..5ad1d5ac57d 100644 --- a/code/modules/mob/living/brain/living_brain.dm +++ b/code/modules/mob/living/brain/living_brain.dm @@ -18,31 +18,14 @@ return ..() /mob/living/brain/say_understands(other)//Goddamn is this hackish, but this say code is so odd - if(isAI(other)) - if(!(container && istype(container, /obj/item/mmi))) - return 0 - else - return 1 - if(istype(other, /mob/living/silicon/decoy)) - if(!(container && istype(container, /obj/item/mmi))) - return 0 - else - return 1 - if(ispAI(other)) - if(!(container && istype(container, /obj/item/mmi))) - return 0 - else - return 1 - if(isrobot(other)) - if(!(container && istype(container, /obj/item/mmi))) - return 0 - else - return 1 + if(!ismob(other)) + return ..() + if(issilicon(other)) + return istype(container, /obj/item/mmi) if(ishuman(other)) - return 1 + return TRUE if(isslime(other)) - return 1 - return ..() + return TRUE /mob/living/brain/ex_act() //you cant blow up brainmobs because it makes transfer_to() freak out when borgs blow up. return diff --git a/code/modules/mob/living/carbon/human/human_emote.dm b/code/modules/mob/living/carbon/human/human_emote.dm index 39712e24151..a85c0158ccf 100644 --- a/code/modules/mob/living/carbon/human/human_emote.dm +++ b/code/modules/mob/living/carbon/human/human_emote.dm @@ -12,7 +12,7 @@ var/mob/living/carbon/human/human_user = user if(!species_custom_messages || (human_user.mind?.miming && !species_custom_mime_messages)) - return . + return var/custom_message if(user.mind?.miming) diff --git a/code/modules/mob/living/carbon/human/human_mob.dm b/code/modules/mob/living/carbon/human/human_mob.dm index 6938a3e3451..59786362d25 100644 --- a/code/modules/mob/living/carbon/human/human_mob.dm +++ b/code/modules/mob/living/carbon/human/human_mob.dm @@ -1448,8 +1448,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X /mob/living/carbon/human/singularity_pull(S, current_size) ..() if(current_size >= STAGE_THREE) - var/list/handlist = list(l_hand, r_hand) - for(var/obj/item/hand in handlist) + for(var/obj/item/hand in get_both_hands(src)) if(prob(current_size * 5) && hand.w_class >= ((11-current_size)/2) && unEquip(hand)) step_towards(hand, src) to_chat(src, "\The [S] pulls \the [hand] from your grip!") diff --git a/code/modules/mob/living/carbon/human/human_say.dm b/code/modules/mob/living/carbon/human/human_say.dm index 0041ca03dbf..f992b4215c7 100644 --- a/code/modules/mob/living/carbon/human/human_say.dm +++ b/code/modules/mob/living/carbon/human/human_say.dm @@ -6,23 +6,24 @@ return " (as [get_id_name("Unknown")])" return ..() -/mob/living/carbon/human/say_understands(mob/other, datum/language/speaking = null) +/mob/living/carbon/human/say_understands(atom/movable/other, datum/language/speaking = null) if(dna.species.can_understand(other)) - return 1 + return TRUE //These only pertain to common. Languages are handled by mob/say_understands() - if(!speaking) + if(!speaking && ismob(other)) if(isnymph(other)) - if(length(other.languages) >= 2) //They've sucked down some blood and can speak common now. - return 1 + var/mob/nymph = other + if(length(nymph.languages) >= 2) //They've sucked down some blood and can speak common now. + return TRUE if(issilicon(other)) - return 1 + return TRUE if(isbot(other)) - return 1 + return TRUE if(isbrain(other)) - return 1 + return TRUE if(isslime(other)) - return 1 + return TRUE return ..() diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm index 4a9fcf2b651..c2eb52766e6 100644 --- a/code/modules/mob/living/carbon/human/species/_species.dm +++ b/code/modules/mob/living/carbon/human/species/_species.dm @@ -317,7 +317,7 @@ ADD_SLOWDOWN(H.r_hand.slowdown) if(ignoreslow) - return . // Only malusses after here + return // Only malusses after here if(H.dna.species.spec_movement_delay()) //Species overrides for slowdown due to feet/legs . += 2 * H.stance_damage //damaged/missing feet or legs is slow diff --git a/code/modules/mob/living/carbon/human/species/diona_species.dm b/code/modules/mob/living/carbon/human/species/diona_species.dm index 8fd6d96e22d..0bd8e688321 100644 --- a/code/modules/mob/living/carbon/human/species/diona_species.dm +++ b/code/modules/mob/living/carbon/human/species/diona_species.dm @@ -63,8 +63,8 @@ /datum/species/diona/can_understand(mob/other) if(isnymph(other)) - return 1 - return 0 + return TRUE + return FALSE /datum/species/diona/on_species_gain(mob/living/carbon/human/H) ..() diff --git a/code/modules/mob/living/living_emote.dm b/code/modules/mob/living/living_emote.dm index dc75d8cf9df..7f94d9ffce1 100644 --- a/code/modules/mob/living/living_emote.dm +++ b/code/modules/mob/living/living_emote.dm @@ -11,7 +11,6 @@ . = ..() if(user.mind?.miming) return FALSE // shh - return . /datum/emote/living/blush key = "blush" diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm index deae1e417da..57f15ef3a41 100644 --- a/code/modules/mob/living/login.dm +++ b/code/modules/mob/living/login.dm @@ -20,5 +20,3 @@ //Should update regardless of if we can ventcrawl, since we can end up in pipes in other ways. update_pipe_vision(loc) - - return . diff --git a/code/modules/mob/living/silicon/ai/ai_say.dm b/code/modules/mob/living/silicon/ai/ai_say.dm index 5f9535b43c1..1e676eb05a3 100644 --- a/code/modules/mob/living/silicon/ai/ai_say.dm +++ b/code/modules/mob/living/silicon/ai/ai_say.dm @@ -3,7 +3,7 @@ */ -/mob/living/silicon/ai/handle_track(message, verb = "says", mob/speaker = null, speaker_name, atom/follow_target, hard_to_hear) +/mob/living/silicon/ai/handle_track(message, verb = "says", atom/movable/speaker = null, speaker_name, atom/follow_target, hard_to_hear) if(hard_to_hear) return @@ -34,9 +34,8 @@ jobname = "Cyborg" else if(ispAI(speaker)) jobname = "Personal AI" - else if(isAutoAnnouncer(speaker)) - var/mob/living/automatedannouncer/AA = speaker - jobname = AA.role + else if(isradio(speaker)) + jobname = "Automated Announcement" else jobname = "Unknown" diff --git a/code/modules/mob/living/silicon/silicon_say.dm b/code/modules/mob/living/silicon/silicon_say.dm index 0420cccf33f..43eae896cac 100644 --- a/code/modules/mob/living/silicon/silicon_say.dm +++ b/code/modules/mob/living/silicon/silicon_say.dm @@ -58,15 +58,15 @@ /mob/living/silicon/say_understands(other, datum/language/speaking = null) //These only pertain to common. Languages are handled by mob/say_understands() - if(!speaking) + if(!speaking && ismob(other)) if(iscarbon(other)) - return 1 + return TRUE if(issilicon(other)) - return 1 + return TRUE if(isbot(other)) - return 1 + return TRUE if(isbrain(other)) - return 1 + return TRUE return ..() //For holopads only. Usable by AI. diff --git a/code/modules/mob/living/simple_animal/friendly/snake.dm b/code/modules/mob/living/simple_animal/friendly/snake.dm index cd7233addf3..2087b05505c 100644 --- a/code/modules/mob/living/simple_animal/friendly/snake.dm +++ b/code/modules/mob/living/simple_animal/friendly/snake.dm @@ -8,7 +8,6 @@ var/mob/living/L = target if(L.reagents && !poison_per_bite == 0) L.reagents.add_reagent(poison_type, poison_per_bite) - return . /mob/living/simple_animal/hostile/retaliate/poison/snake name = "snake" diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index 7e98435c073..f59b35b46e2 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -605,7 +605,7 @@ Difficulty: Hard return FALSE if(mover == caster.pulledby) return TRUE - if(istype(mover, /obj/item/projectile)) + if(isprojectile(mover)) var/obj/item/projectile/P = mover if(P.firer == caster) return TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm index 4d4e048ce32..5c1a666f9b1 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm @@ -181,7 +181,7 @@ if(!(M.mobility_flags & MOBILITY_MOVE)) return TRUE return prob(80) - if(istype(mover, /obj/item/projectile)) + if(isprojectile(mover)) return prob(20) return ..() diff --git a/code/modules/mob/mob_misc_procs.dm b/code/modules/mob/mob_misc_procs.dm index 7aa785514dc..2a8d5934060 100644 --- a/code/modules/mob/mob_misc_procs.dm +++ b/code/modules/mob/mob_misc_procs.dm @@ -74,7 +74,7 @@ /mob/living/carbon/human/get_screen_colour() //Fetch the colour matrix from wherever (e.g. eyes) so it can be compared to client.color. . = ..() if(.) - return . + return var/obj/item/clothing/glasses/worn_glasses = glasses var/obj/item/organ/internal/eyes/eyes = get_int_organ(/obj/item/organ/internal/eyes) diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index f7f5e5a38c8..2f7ac040189 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -6,7 +6,7 @@ if(height==0) return 1 - if(istype(mover, /obj/item/projectile)) + if(isprojectile(mover)) return projectile_hit_check(mover) if(mover.throwing) return (!density || horizontal || (mover.throwing.thrower == src)) diff --git a/code/modules/mob/mob_say_base.dm b/code/modules/mob/mob_say_base.dm index 9182f8e6e35..6b193b3fe96 100644 --- a/code/modules/mob/mob_say_base.dm +++ b/code/modules/mob/mob_say_base.dm @@ -69,36 +69,41 @@ create_log(DEADCHAT_LOG, message) log_ghostsay(message, src) -/mob/proc/say_understands(mob/other, datum/language/speaking = null) +/** + * Checks if the mob can understand the other speaker + * + * If it return FALSE, then the message will have some letters replaced with stars from the heard message +*/ +/mob/proc/say_understands(atom/movable/other, datum/language/speaking = null) if(stat == DEAD) - return 1 + return TRUE //Universal speak makes everything understandable, for obvious reasons. if(universal_speak || universal_understand) - return 1 + return TRUE //Languages are handled after. if(!speaking) - if(!other) - return 1 - if(other.universal_speak) - return 1 - if(isAI(src) && ispAI(other)) - return 1 - if(istype(other, src.type) || istype(src, other.type)) - return 1 - return 0 + if(!other || !ismob(other)) + return TRUE + var/mob/other_mob = other + if(other_mob.universal_speak) + return TRUE + if(isAI(src) && ispAI(other_mob)) + return TRUE + if(istype(other_mob, src.type) || istype(src, other_mob.type)) + return TRUE + return FALSE if(speaking.flags & INNATE) - return 1 + return TRUE //Language check. for(var/datum/language/L in languages) if(speaking.name == L.name) - return 1 - - return 0 + return TRUE + return FALSE /mob/proc/say_quote(message, datum/language/speaking = null) var/verb = "says" diff --git a/code/modules/power/cables/cable.dm b/code/modules/power/cables/cable.dm index a6757fd34be..18d73085e04 100644 --- a/code/modules/power/cables/cable.dm +++ b/code/modules/power/cables/cable.dm @@ -336,8 +336,6 @@ By design, d1 is the smallest direction and d2 is the highest T = get_turf(src) . += T.power_list(src, d2) //get on turf matching cables - return . - //should be called after placing a cable which extends another cable, creating a "smooth" cable that no longer terminates in the centre of a turf. //needed as this can, unlike other placements, disconnect cables /obj/structure/cable/proc/denode() diff --git a/code/modules/power/engines/singularity/singularity.dm b/code/modules/power/engines/singularity/singularity.dm index 3fcf4600a74..f9da157db0d 100644 --- a/code/modules/power/engines/singularity/singularity.dm +++ b/code/modules/power/engines/singularity/singularity.dm @@ -519,7 +519,7 @@ /obj/effect/abstract/proximity_checker/singulo/Crossed(atom/movable/AM, oldloc) . = ..() - if(!istype(AM, /obj/item/projectile)) + if(!isprojectile(AM)) return var/obj/item/projectile/P = AM var/distance = distance_to_singulo diff --git a/code/modules/power/engines/supermatter/supermatter.dm b/code/modules/power/engines/supermatter/supermatter.dm index cf777dbae3b..3fc0b2826da 100644 --- a/code/modules/power/engines/supermatter/supermatter.dm +++ b/code/modules/power/engines/supermatter/supermatter.dm @@ -328,7 +328,7 @@ var/turf/T = get_turf(M) if(istype(T) && atoms_share_level(T, src)) // if the player is on the same zlevel as the SM shared SEND_SOUND(M, sound('sound/machines/engine_alert2.ogg')) // then send them the sound file - radio.autosay(speaking, name, null, list(z)) + radio.autosay(speaking, name, null) for(var/i in SUPERMATTER_COUNTDOWN_TIME to 0 step -10) if(!processes) // Stop exploding if you're frozen by an admin, damn you cut_overlay(causality_field, TRUE) @@ -336,7 +336,7 @@ damage = explosion_point - 1 // One point below exploding, so it will re-start the countdown once unfrozen return if(damage < explosion_point) // Cutting it a bit close there engineers - radio.autosay("[safe_alert] Failsafe has been disengaged.", name, null, list(z)) + radio.autosay("[safe_alert] Failsafe has been disengaged.", name, null) cut_overlay(causality_field, TRUE) final_countdown = FALSE remove_filter(list("outline", "icon")) @@ -348,7 +348,7 @@ speaking = "[DisplayTimeText(i, TRUE)] remain before causality stabilization." else speaking = "[i*0.1]..." - radio.autosay(speaking, name, null, list(z)) + radio.autosay(speaking, name, null) sleep(10) explode() @@ -648,27 +648,27 @@ //Oh shit it's bad, time to freak out if(damage > emergency_point) - radio.autosay("[emergency_alert] Integrity: [get_integrity()]%", name, null, list(z)) + radio.autosay("[emergency_alert] Integrity: [get_integrity()]%", name, null) lastwarning = REALTIMEOFDAY if(!has_reached_emergency) investigate_log("has reached the emergency point for the first time.", "supermatter") message_admins("[src] has reached the emergency point [ADMIN_JMP(src)].") has_reached_emergency = TRUE else if(damage >= damage_archived) // The damage is still going up - radio.autosay("[warning_alert] Integrity: [get_integrity()]%", name, "Engineering", list(z)) + radio.autosay("[warning_alert] Integrity: [get_integrity()]%", name, "Engineering") lastwarning = REALTIMEOFDAY - (WARNING_DELAY * 5) else // Phew, we're safe - radio.autosay("[safe_alert] Integrity: [get_integrity()]%", name, "Engineering", list(z)) + radio.autosay("[safe_alert] Integrity: [get_integrity()]%", name, "Engineering") lastwarning = REALTIMEOFDAY if(power > POWER_PENALTY_THRESHOLD) - radio.autosay("Warning: Hyperstructure has reached dangerous power level.", name, "Engineering", list(z)) + radio.autosay("Warning: Hyperstructure has reached dangerous power level.", name, "Engineering") if(powerloss_inhibitor < 0.5) - radio.autosay("DANGER: CHARGE INERTIA CHAIN REACTION IN PROGRESS.", name, "Engineering", list(z)) + radio.autosay("DANGER: CHARGE INERTIA CHAIN REACTION IN PROGRESS.", name, "Engineering") if(combined_gas > MOLE_CRUNCH_THRESHOLD) - radio.autosay("Warning: Critical coolant mass reached.", name, "Engineering", list(z)) + radio.autosay("Warning: Critical coolant mass reached.", name, "Engineering") //Boom (Mind blown) if(damage > explosion_point) countdown() diff --git a/code/modules/power/engines/supermatter/supermatter_event.dm b/code/modules/power/engines/supermatter/supermatter_event.dm index db17530f41e..8af8c5ef9b3 100644 --- a/code/modules/power/engines/supermatter/supermatter_event.dm +++ b/code/modules/power/engines/supermatter/supermatter_event.dm @@ -43,12 +43,12 @@ /datum/supermatter_event/proc/sm_radio_say(text) if(!text) return - supermatter.radio.autosay(text, supermatter, "Engineering", list(supermatter.z)) + supermatter.radio.autosay(text, supermatter, "Engineering") /datum/supermatter_event/proc/general_radio_say(text) if(!text) return - supermatter.radio.autosay(text, supermatter, null, list(supermatter.z)) + supermatter.radio.autosay(text, supermatter, null) // Below this are procs used for the SM events, in order of severity diff --git a/code/modules/power/generators/turbine.dm b/code/modules/power/generators/turbine.dm index a9e7ca43a04..cd8a1078922 100644 --- a/code/modules/power/generators/turbine.dm +++ b/code/modules/power/generators/turbine.dm @@ -174,7 +174,7 @@ starter = FALSE last_overheat = world.time overheat -= 50 - radio.autosay(OVERHEAT_MESSAGE, name, "Engineering", list(z)) + radio.autosay(OVERHEAT_MESSAGE, name, "Engineering") playsound(src, 'sound/machines/buzz-two.ogg', 100, FALSE, 40, 30, falloff_distance = 10) /obj/machinery/power/compressor/proc/time_until_overheat_done() diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 0e33fbc6ef4..b5365256fe8 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -35,6 +35,8 @@ var/semicd = 0 //cooldown handler var/execution_speed = 6 SECONDS var/weapon_weight = WEAPON_LIGHT + /// Additional spread when dual wielding. + var/dual_wield_spread = 24 var/list/restricted_species var/spread = 0 @@ -201,7 +203,7 @@ continue else if(G.can_trigger_gun(user)) if(!HAS_TRAIT(user, TRAIT_BADASS)) - bonus_spread += 24 * G.weapon_weight + bonus_spread += dual_wield_spread * G.weapon_weight loop_counter++ addtimer(CALLBACK(G, PROC_REF(process_fire), target, user, 1, params, null, bonus_spread), loop_counter) diff --git a/code/modules/projectiles/guns/energy_guns.dm b/code/modules/projectiles/guns/energy_guns.dm index 67f2d45398c..5980eaad8ec 100644 --- a/code/modules/projectiles/guns/energy_guns.dm +++ b/code/modules/projectiles/guns/energy_guns.dm @@ -200,7 +200,7 @@ if(can_shoot()) user.visible_message("[user] is putting the barrel of [src] in [user.p_their()] mouth. It looks like [user.p_theyre()] trying to commit suicide!") sleep(25) - if(user.l_hand == src || user.r_hand == src) + if(user.is_holding(src)) user.visible_message("[user] melts [user.p_their()] face off with [src]!") playsound(loc, fire_sound, 50, 1, -1) var/obj/item/ammo_casing/energy/shot = ammo_type[select] diff --git a/code/modules/projectiles/guns/projectile_gun.dm b/code/modules/projectiles/guns/projectile_gun.dm index 37d17ed38d4..25dc5282cb4 100644 --- a/code/modules/projectiles/guns/projectile_gun.dm +++ b/code/modules/projectiles/guns/projectile_gun.dm @@ -148,7 +148,7 @@ if(loc == user) if(suppressed && can_unsuppress) var/obj/item/suppressor/S = suppressed - if(user.l_hand != src && user.r_hand != src) + if(!user.is_holding(src)) ..() return to_chat(user, "You unscrew [suppressed] from [src].") @@ -198,7 +198,7 @@ if(chambered && chambered.BB && !chambered.BB.nodamage) user.visible_message("[user] is putting the barrel of [src] in [user.p_their()] mouth. It looks like [user.p_theyre()] trying to commit suicide!") sleep(25) - if(user.l_hand == src || user.r_hand == src) + if(user.is_holding(src)) process_fire(user, user, 0, zone_override = "head") user.visible_message("[user] blows [user.p_their()] brains out with [src]!") return BRUTELOSS diff --git a/code/modules/projectiles/guns/syringe_gun.dm b/code/modules/projectiles/guns/syringe_gun.dm index 7c678e630ca..c930fb9efa2 100644 --- a/code/modules/projectiles/guns/syringe_gun.dm +++ b/code/modules/projectiles/guns/syringe_gun.dm @@ -406,6 +406,7 @@ desc = "Fire syringes at a short distance." icon_state = "blowgun" item_state = "gun" + trigger_guard = TRIGGER_GUARD_ALLOW_ALL // you fire it with your mouth /obj/item/gun/syringe/blowgun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0) if(chambered.BB) diff --git a/code/modules/projectiles/projectile/magic_projectiles.dm b/code/modules/projectiles/projectile/magic_projectiles.dm index 1d21a315982..8ccc59ffc30 100644 --- a/code/modules/projectiles/projectile/magic_projectiles.dm +++ b/code/modules/projectiles/projectile/magic_projectiles.dm @@ -357,7 +357,7 @@ GLOBAL_LIST_INIT(wabbajack_docile_animals, list( qdel(src) else var/obj/O = change - if(istype(O, /obj/item/gun)) + if(isgun(O)) new /mob/living/simple_animal/hostile/mimic/copy/ranged(O.loc, O, firer) else new /mob/living/simple_animal/hostile/mimic/copy(O.loc, O, firer) diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 38b67f3c086..f273631c1f5 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -524,7 +524,7 @@ /obj/machinery/disposal/CanPass(atom/movable/mover, turf/target, height=0) if(isitem(mover) && mover.throwing) var/obj/item/I = mover - if(istype(I, /obj/item/projectile)) + if(isprojectile(I)) return if(prob(75) || (istype(mover.throwing.thrower) && (HAS_TRAIT(mover.throwing.thrower, TRAIT_BADASS) || HAS_TRAIT(mover.throwing.thrower, TRAIT_NEVER_MISSES_DISPOSALS)))) I.forceMove(src) diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index a1258bf72d9..8fae073f154 100644 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -285,7 +285,7 @@ return /obj/machinery/disposal/deliveryChute/Bumped(atom/movable/AM) //Go straight into the chute - if(istype(AM, /obj/item/projectile) || isAI(AM) || QDELETED(AM)) + if(isprojectile(AM) || isAI(AM) || QDELETED(AM)) return switch(dir) if(NORTH) diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index fde9a420793..7ba2fec07b2 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -539,7 +539,7 @@ H.AIStatus = AI_OFF H.LoseTarget() stopped_atoms |= M - else if(istype(A, /obj/item/projectile)) + else if(isprojectile(A)) var/obj/item/projectile/P = A P.paused = TRUE stopped_atoms |= P diff --git a/code/modules/ruins/lavalandruin_code/sin_ruins.dm b/code/modules/ruins/lavalandruin_code/sin_ruins.dm index 8d9ed669b8c..13033d10fe0 100644 --- a/code/modules/ruins/lavalandruin_code/sin_ruins.dm +++ b/code/modules/ruins/lavalandruin_code/sin_ruins.dm @@ -117,7 +117,7 @@ /obj/structure/cursed_money/attack_hand(mob/living/user) . = ..() if(.) - return . + return user.visible_message("[user] opens the bag and \ and removes a die. The bag then vanishes.", diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 13fcbb8952c..70c8c5e4646 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -185,12 +185,6 @@ //returns first-found touching shuttleport /obj/docking_port/stationary/get_docked() return locate(/obj/docking_port/mobile) in loc - /* - for(var/turf/T in return_ordered_turfs()) - . = locate(/obj/docking_port/mobile) in loc - if(.) - return . - */ /obj/docking_port/stationary/transit name = "In transit" diff --git a/code/modules/shuttle/syndicate_shuttles.dm b/code/modules/shuttle/syndicate_shuttles.dm index 76f3556883a..697819a586a 100644 --- a/code/modules/shuttle/syndicate_shuttles.dm +++ b/code/modules/shuttle/syndicate_shuttles.dm @@ -1,4 +1,4 @@ -#define SYNDICATE_CHALLENGE_TIMER 12000 //20 minutes +#define SYNDICATE_CHALLENGE_TIMER 20 MINUTES /obj/machinery/computer/shuttle/syndicate name = "syndicate shuttle terminal" diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index 0088aaa7fdc..2c7806b9dce 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -690,7 +690,7 @@ set_light(3) addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, set_light), 0), 0.25 SECONDS) - if(istype(hitby, /obj/item/projectile)) + if(isprojectile(hitby)) var/obj/item/projectile/P = hitby if(P.shield_buster || istype(P, /obj/item/projectile/ion)) //EMP's and unpariable attacks, after all. return FALSE diff --git a/icons/effects/mouse_pointers/weapon_pointer.dmi b/icons/effects/mouse_pointers/weapon_pointer.dmi new file mode 100644 index 00000000000..b5070062c0b Binary files /dev/null and b/icons/effects/mouse_pointers/weapon_pointer.dmi differ diff --git a/icons/misc/buildmode.dmi b/icons/misc/buildmode.dmi index 0520a9ef005..663d4546caf 100644 Binary files a/icons/misc/buildmode.dmi and b/icons/misc/buildmode.dmi differ diff --git a/icons/obj/economy.dmi b/icons/obj/economy.dmi index 06a2a97e883..03f10400f45 100644 Binary files a/icons/obj/economy.dmi and b/icons/obj/economy.dmi differ diff --git a/paradise.dme b/paradise.dme index 395bb3eb17f..bdac76b5105 100644 --- a/paradise.dme +++ b/paradise.dme @@ -406,6 +406,7 @@ #include "code\datums\components\edit_complainer.dm" #include "code\datums\components\emissive_blocker.dm" #include "code\datums\components\footstep.dm" +#include "code\datums\components\fullauto.dm" #include "code\datums\components\label.dm" #include "code\datums\components\largeobjecttransparency.dm" #include "code\datums\components\material_container.dm" @@ -1597,6 +1598,7 @@ #include "code\modules\buildmode\buildmode_hud.dm" #include "code\modules\buildmode\effects\line.dm" #include "code\modules\buildmode\submodes\advanced.dm" +#include "code\modules\buildmode\submodes\antirad_mode.dm" #include "code\modules\buildmode\submodes\area_edit.dm" #include "code\modules\buildmode\submodes\atmos.dm" #include "code\modules\buildmode\submodes\basic.dm" diff --git a/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss b/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss index 996aacc3bf1..1e72f6edd8f 100644 --- a/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss +++ b/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss @@ -12,7 +12,7 @@ img { margin: 0; padding: 0; line-height: 1; - -ms-interpolation-mode: nearest-neighbor; + -ms-interpolation-mode: nearest-neighbor; // TODO: Remove with 516 image-rendering: pixelated; } diff --git a/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss b/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss index b2f85f3195c..42970e8f119 100644 --- a/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss +++ b/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss @@ -30,7 +30,7 @@ img { margin: 0; padding: 0; line-height: 1; - -ms-interpolation-mode: nearest-neighbor; + -ms-interpolation-mode: nearest-neighbor; // TODO: Remove with 516 image-rendering: pixelated; } @@ -183,12 +183,6 @@ a.popt { padding: 2px 0; } -.filterMessages input { -} - -.filterMessages label { -} - .icon-stack { height: 1em; line-height: 1em; diff --git a/tgui/packages/tgui/components/NanoMap.js b/tgui/packages/tgui/components/NanoMap.js index a745cd1f38c..318933dbbe4 100644 --- a/tgui/packages/tgui/components/NanoMap.js +++ b/tgui/packages/tgui/components/NanoMap.js @@ -118,7 +118,8 @@ export class NanoMap extends Component { top: '50%', left: '50%', transform: 'translate(-50%, -50%)', - '-ms-interpolation-mode': 'nearest-neighbor', + '-ms-interpolation-mode': 'nearest-neighbor', // TODO: Remove with 516 + 'image-rendering': 'pixelated', }; return ( diff --git a/tgui/packages/tgui/interfaces/CloningConsole.js b/tgui/packages/tgui/interfaces/CloningConsole.js index 9020d13f31b..e7819e6d44d 100644 --- a/tgui/packages/tgui/interfaces/CloningConsole.js +++ b/tgui/packages/tgui/interfaces/CloningConsole.js @@ -86,7 +86,8 @@ const CloningConsoleMain = (props, context) => { )} style={{ width: '100%', - '-ms-interpolation-mode': 'nearest-neighbor', + '-ms-interpolation-mode': 'nearest-neighbor', // TODO: Remove with 516 + 'image-rendering': 'pixelated', }} />