diff --git a/.github/workflows/compile_changelogs.yml b/.github/workflows/compile_changelogs.yml index 141fc9a7d8..f8098df66e 100644 --- a/.github/workflows/compile_changelogs.yml +++ b/.github/workflows/compile_changelogs.yml @@ -17,6 +17,7 @@ jobs: run: | python -m pip install --upgrade pip python -m pip install pyyaml + sudo apt-get install dos2unix - name: "Checkout" uses: actions/checkout@v1 with: @@ -24,6 +25,9 @@ jobs: - name: "Compile" run: | python tools/ss13_genchangelog.py html/changelog.html html/changelogs + - name: "Convert Lineendings" + run: | + unix2dos html/changelogs/.all_changelog.yml - name: Commit run: | git config --local user.email "action@github.com" diff --git a/README.md b/README.md index 2a1ffe65ec..0ecf4c5b01 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,28 @@ ## Citadel Station 13 Based and maintained from /tg/station. -[![forthebadge](http://forthebadge.com/images/badges/60-percent-of-the-time-works-every-time.svg)](https://forthebadge.com) [![forthebadge](http://forthebadge.com/images/badges/pretty-risque.svg)](https://forthebadge.com) [![forthebadge](http://forthebadge.com/images/badges/you-didnt-ask-for-this.svg)](http://forthebadge.com) +[![Build Status](https://api.travis-ci.org/Citadel-Station-13/Citadel-Station-13.png)](https://travis-ci.org/Citadel-Station-13/Citadel-Station-13) +[![Percentage of issues still open](http://isitmaintained.com/badge/open/Citadel-Station-13/Citadel-Station-13.svg)](http://isitmaintained.com/project/Citadel-Station-13/Citadel-Station-13 "Percentage of issues still open") +[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/Citadel-Station-13/Citadel-Station-13.svg)](http://isitmaintained.com/project/Citadel-Station-13/Citadel-Station-13 "Average time to resolve an issue") -[![forinfinityandbyond](https://user-images.githubusercontent.com/5211576/29499758-4efff304-85e6-11e7-8267-62919c3688a9.gif)](https://www.reddit.com/r/SS13/comments/5oplxp/what_is_the_main_problem_with_byond_as_an_engine/dclbu1a) - -[![Build Status](https://api.travis-ci.org/Citadel-Station-13/Citadel-Station-13.png)](https://travis-ci.org/Citadel-Station-13/Citadel-Station-13) [![Krihelimeter](http://www.krihelinator.xyz/badge/Citadel-Station-13/Citadel-Station-13)](http://www.krihelinator.xyz) - -[![Percentage of issues still open](http://isitmaintained.com/badge/open/Citadel-Station-13/Citadel-Station-13.svg)](http://isitmaintained.com/project/Citadel-Station-13/Citadel-Station-13 "Percentage of issues still open") [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/Citadel-Station-13/Citadel-Station-13.svg)](http://isitmaintained.com/project/Citadel-Station-13/Citadel-Station-13 "Average time to resolve an issue") +[![forthebadge](http://forthebadge.com/images/badges/60-percent-of-the-time-works-every-time.svg)](https://forthebadge.com) [![forthebadge](http://forthebadge.com/images/badges/pretty-risque.svg)](https://forthebadge.com) [![forthebadge](http://forthebadge.com/images/badges/you-didnt-ask-for-this.svg)](http://forthebadge.com) [![forinfinityandbyond](https://user-images.githubusercontent.com/5211576/29499758-4efff304-85e6-11e7-8267-62919c3688a9.gif)](https://www.reddit.com/r/SS13/comments/5oplxp/what_is_the_main_problem_with_byond_as_an_engine/dclbu1a) **Upstream Information** -**Website:** https://tgstation13.org -**Code:** https://github.com/tgstation/tgstation -**Wiki** https://tgstation13.org/wiki/Main_Page -**IRC:** irc://irc.rizon.net/coderbus or if you dont have an IRC client, you can click [here](https://kiwiirc.com/client/irc.rizon.net:6667/?&theme=cli#coderbus). - +* **Website:** +* **Code:** +* **Wiki:** +* **Codedocs:** +* **/tg/station Discord:** +* **Coderbus Discord:** +* ~~**IRC:** ~~ (dead) + **Citadel Station Information** -**Website:** http://citadel-station.net -**Forums:** http://citadel-station.net/forum -**Ban Appeals:** http://citadel-station.net/forum/forumdisplay.php?fid=8 -**Code:** https://github.com/Citadel-Station-13/Citadel-Station-13 -**Discord:** [Here](https://discord.gg/E6SQuhz) +* **Website:** +* **Code:** +* **Wiki:** +* **Forums:** +* **Ban Appeals:** +* **Discord:** ## DOWNLOADING @@ -162,13 +164,12 @@ All code before [commit 333c566b88108de218d882840e61928a9b759d8f on 2014/31/12 a See LICENSE and GPLv3.txt for more details. +The TGS3 API is licensed as a subproject under the MIT license. + +See the footers of code/\_\_DEFINES/server\_tools.dm, code/modules/server\_tools/st\_commands.dm, and code/modules/server\_tools/st\_inteface.dm for the MIT license. + tgui clientside is licensed as a subproject under the MIT license. Font Awesome font files, used by tgui, are licensed under the SIL Open Font License v1.1 tgui assets are licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/). -The TGS3 API is licensed as a subproject under the MIT license. -See tgui/LICENSE.md for the MIT license. -See tgui/assets/fonts/SIL-OFL-1.1-LICENSE.md for the SIL Open Font License. -See the footers of code/\_\_DEFINES/server\_tools.dm, code/modules/server\_tools/st\_commands.dm, and code/modules/server\_tools/st\_inteface.dm for the MIT license. - -All assets including icons and sound are under a [Creative Commons 3.0 BY-SA license](http://creativecommons.org/licenses/by-sa/3.0/) unless otherwise indicated. +All assets including icons and sound are under a [Creative Commons 3.0 BY-SA license](https://creativecommons.org/licenses/by-sa/3.0/) unless otherwise indicated. diff --git a/_maps/RandomRuins/IceRuins/icemoon_surface_engioutpost.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_engioutpost.dmm index 8ae3ff1f62..cfc9e5f4ce 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_surface_engioutpost.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_surface_engioutpost.dmm @@ -5,10 +5,6 @@ "ab" = ( /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) -"ac" = ( -/obj/effect/mob_spawn/human/engineer/rig, -/turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) "ad" = ( /obj/machinery/power/floodlight, /obj/structure/cable{ @@ -176,10 +172,9 @@ /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "aI" = ( -/obj/item/pda/engineering{ - note = "To-do: Check on singularity status. Get a pint at eat. Nag the research manager for RCDs." - }, -/turf/open/floor/plating/asteroid/snow/icemoon, +/obj/effect/turf_decal/stripes/line, +/obj/item/clothing/suit/space/hardsuit/engine, +/turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "aJ" = ( /obj/effect/decal/cleanable/dirt, @@ -270,12 +265,6 @@ /obj/machinery/atmospherics/pipe/manifold/cyan/visible{ dir = 1 }, -/obj/effect/turf_decal/stripes/corner{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/corner{ - dir = 1 - }, /obj/machinery/light/small{ dir = 1 }, @@ -304,9 +293,6 @@ /obj/machinery/atmospherics/pipe/manifold/green/visible{ dir = 1 }, -/obj/effect/turf_decal/stripes/corner{ - dir = 1 - }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "ba" = ( @@ -346,20 +332,10 @@ /obj/effect/decal/cleanable/blood/splatter, /turf/open/floor/plating/asteroid/snow/icemoon, /area/icemoon/surface/outdoors) -"be" = ( -/obj/item/card/id{ - access = list(200,204,11,12,10); - assignment = "Senior Station Engineer"; - desc = "A card used to provide ID and determine access across the station. There's blood dripping from the corner. Ew."; - name = "George 'Plastic' Miller's ID Card (Senior Station Engineer)"; - registered_name = "George 'Plastic' Miller" - }, -/turf/open/floor/plating/asteroid/snow/icemoon, -/area/icemoon/surface/outdoors) "bf" = ( -/obj/effect/gibspawner/generic, /obj/effect/decal/cleanable/blood, /obj/effect/decal/cleanable/blood/gibs/core, +/obj/item/clothing/suit/space/hardsuit/engine, /turf/open/floor/plating/asteroid/snow/icemoon, /area/icemoon/surface/outdoors) "bg" = ( @@ -544,10 +520,6 @@ /obj/item/shard/plasma, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) -"bz" = ( -/obj/item/clothing/suit/space/hardsuit/engine, -/turf/open/floor/plating/asteroid/snow/icemoon, -/area/icemoon/surface/outdoors) "bA" = ( /obj/item/flashlight/flare, /turf/open/floor/plating/asteroid/snow/icemoon, @@ -964,10 +936,6 @@ /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "cO" = ( -/obj/effect/turf_decal/stripes/corner, -/obj/effect/turf_decal/stripes/corner{ - dir = 8 - }, /obj/machinery/light/small, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) @@ -982,9 +950,6 @@ /obj/machinery/atmospherics/pipe/simple/dark/visible{ dir = 9 }, -/obj/effect/turf_decal/stripes/corner{ - dir = 8 - }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "cR" = ( @@ -1013,13 +978,6 @@ }, /turf/open/floor/plating/icemoon, /area/icemoon/surface/outdoors) -"cU" = ( -/obj/effect/mob_spawn/human/engineer/rig, -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/open/floor/plating/icemoon, -/area/icemoon/surface/outdoors) "cV" = ( /obj/effect/turf_decal/trimline/neutral/filled/line, /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -1032,12 +990,7 @@ }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) -"cX" = ( -/obj/machinery/rnd/production/circuit_imprinter, -/turf/open/floor/plating/snowed/smoothed/icemoon, -/area/icemoon/surface/outdoors) "cY" = ( -/obj/machinery/rnd/production/protolathe/department/engineering, /obj/machinery/light/small/broken, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) @@ -1249,6 +1202,10 @@ }, /turf/open/floor/plating/icemoon, /area/icemoon/surface/outdoors) +"xh" = ( +/mob/living/simple_animal/hostile/bear/snow, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/icemoon/surface/outdoors) "CR" = ( /obj/structure/cable{ icon_state = "0-8" @@ -1310,17 +1267,17 @@ aa ak an ak -ae +ak an ab aa by bQ bQ +aO ae -ae -ae -ae +ak +ak ae aO aa @@ -1437,9 +1394,9 @@ aa aa aa aa -aI aa -be +aa +aa aa aa aa @@ -1452,7 +1409,7 @@ ak aa "} (9,1,1) = {" -ac +ab ab al ap @@ -1461,7 +1418,7 @@ aa aa aa bf -bz +aa aa aa af @@ -1507,7 +1464,7 @@ bA aa aa af -cA +aI DM dc al @@ -1529,7 +1486,7 @@ aa ab ab cF -cU +gA al al aO @@ -1595,28 +1552,28 @@ al al al ds -ae +aO aa "} (16,1,1) = {" -ae -ae -ae -ae +aO +aO ae ae ae aO +ae +aO bi ae +aO ae ae +aO ae +aO ae -ae -ae -ae -ae +aO aa "} (17,1,1) = {" @@ -1630,7 +1587,7 @@ ae aL bb bD -ae +aO aa aa aa @@ -1665,9 +1622,9 @@ aa af aa aa -aa +ak an -aB +dj ae aP bk @@ -1675,7 +1632,7 @@ aP ae aB aB -aB +dj aB aB aB @@ -1698,7 +1655,7 @@ cf cr cB cI -cX +ab aB aa aa @@ -1720,7 +1677,7 @@ aB cE ab cY -aB +dj aa aa "} @@ -1731,7 +1688,7 @@ af ab ab ab -ab +xh ab bj ab @@ -1741,7 +1698,7 @@ aP cH ab de -aB +dj aa aa "} @@ -1857,7 +1814,7 @@ aa aa an an -aB +dj ae bj bH @@ -1903,7 +1860,7 @@ aa ae bq bH -ae +aO aa aa aa @@ -1926,9 +1883,9 @@ bq bJ ae ae +aO ae -ae -ae +aO aa aa aa @@ -1949,10 +1906,10 @@ bZ ck cs cL +aO ae ae -ae -ae +aO aa "} (33,1,1) = {" @@ -2004,7 +1961,7 @@ aa ae ae ae -ae +aO aW bu bN @@ -2013,9 +1970,9 @@ cn cv cO ae -ae -ae -ae +aO +aO +aO aa "} (36,1,1) = {" @@ -2065,8 +2022,8 @@ aa aa aa ae -ae -ae +aO +aO ae aZ bu @@ -2076,9 +2033,9 @@ cd cy cQ ae -ae -ae -ae +aO +aO +aO aa "} (39,1,1) = {" @@ -2110,14 +2067,14 @@ aa aa aa ae +aO +aO ae ae ae +aO ae -ae -ae -ae -ae +aO aa aa aa diff --git a/_maps/RandomRuins/IceRuins/icemoon_surface_hotsprings.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_hotsprings.dmm index d920cc03c5..93b221c446 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_surface_hotsprings.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_surface_hotsprings.dmm @@ -1,6 +1,6 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE "a" = ( -/turf/open/floor/plating/asteroid/snow/icemoon, +/turf/closed/indestructible/riveted/uranium, /area/icemoon/surface/outdoors) "b" = ( /turf/closed/mineral/random/snow/no_caves, @@ -12,7 +12,17 @@ /obj/item/paper/crumpled{ info = "When one falls into this hot spring, they shall forever be turned into..." }, -/turf/open/floor/plating/asteroid/snow/icemoon, +/turf/open/floor/plating/beach/sand, +/area/icemoon/surface/outdoors) +"I" = ( +/turf/closed/indestructible/fakeglass, +/area/icemoon/surface/outdoors) +"L" = ( +/obj/structure/fluff/beach_umbrella, +/turf/open/floor/plating/beach/sand, +/area/icemoon/surface/outdoors) +"U" = ( +/turf/open/floor/plating/beach/sand, /area/icemoon/surface/outdoors) (1,1,1) = {" @@ -34,7 +44,7 @@ b b a a -a +I a a b @@ -45,11 +55,11 @@ b b b a -a -a -a -a -a +U +U +U +U +U a b b @@ -57,65 +67,65 @@ b (4,1,1) = {" b a -a -a +U +L c c c -a -a +U +U a b "} (5,1,1) = {" b a -a +U c c c c c -a +U a b "} (6,1,1) = {" b -a -a +I +U c c c c c -a -a +U +I b "} (7,1,1) = {" b a -a +U c c c c c -a +U a b "} (8,1,1) = {" b a -a -a +U +L c c c -a -a +U +U a b "} @@ -123,11 +133,11 @@ b b b a -a -a +U +U d -a -a +U +U a b b @@ -138,7 +148,7 @@ b b a a -a +I a a b diff --git a/_maps/RandomRuins/IceRuins/icemoon_surface_lust.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_lust.dmm index 5e68de864f..704ac63a7d 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_surface_lust.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_surface_lust.dmm @@ -20,12 +20,6 @@ }, /turf/open/floor/mineral/diamond, /area/icemoon/surface/outdoors) -"f" = ( -/obj/structure/sign/poster/contraband/lusty_xenomorph, -/obj/structure/falsewall/abductor, -/obj/structure/fans/tiny, -/turf/open/floor/mineral/diamond, -/area/icemoon/surface/outdoors) (1,1,1) = {" a @@ -101,7 +95,7 @@ d e d c -f +b a a "} diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_village.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_village.dmm index 908363dd86..35eb1901f6 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_village.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_village.dmm @@ -198,6 +198,9 @@ /obj/structure/toilet{ dir = 1 }, +/mob/living/simple_animal/hostile/skeleton/eskimo{ + name = "Village Hunter" + }, /turf/open/floor/plating, /area/ruin/powered) "sY" = ( @@ -216,6 +219,9 @@ /area/icemoon/underground/explored) "tt" = ( /obj/effect/decal/cleanable/dirt, +/mob/living/simple_animal/hostile/skeleton/eskimo{ + name = "Village Hunter" + }, /turf/open/floor/plasteel/freezer, /area/ruin/powered) "tF" = ( @@ -415,6 +421,12 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/carpet, /area/ruin/powered) +"IT" = ( +/mob/living/simple_animal/hostile/skeleton/eskimo{ + name = "Village Hunter" + }, +/turf/open/floor/wood, +/area/ruin/powered) "Kd" = ( /obj/structure/flora/grass/green, /turf/open/floor/plating/asteroid/snow/icemoon, @@ -816,7 +828,7 @@ tF ac Vn AG -aM +IT yb Vn wQ diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm index b4abf9b535..80ad86e3c5 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm @@ -476,7 +476,7 @@ }, /obj/item/storage/bag/plants/portaseeder, /obj/item/seeds/cotton, -/obj/item/seeds/cotton, +/obj/item/seeds/cotton/durathread, /turf/open/indestructible/boss, /area/ruin/unpowered/ash_walkers) "bk" = ( diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm index b22c9787ba..dab9d0316b 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm @@ -61,8 +61,7 @@ }, /obj/structure/sign/barsign{ pixel_y = -32; - req_access = null; - req_access_txt = "0" + req_access = null }, /turf/open/floor/wood, /area/ruin/unpowered/syndicate_lava_base/bar) @@ -212,7 +211,6 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /obj/machinery/computer/arcade/orion_trail{ - icon_state = "arcade"; dir = 1 }, /turf/open/floor/plasteel/dark, @@ -270,7 +268,6 @@ dir = 4 }, /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /obj/machinery/light/small{ @@ -1501,7 +1498,6 @@ /area/ruin/unpowered/syndicate_lava_base/virology) "fk" = ( /obj/machinery/power/apc/syndicate{ - dir = 2; name = "Experimentation Lab APC"; pixel_y = -24 }, @@ -1565,15 +1561,10 @@ /obj/machinery/door/firedoor, /obj/structure/table/reinforced, /obj/machinery/door/window/southleft{ - base_state = "left"; - dir = 2; - icon_state = "left"; name = "Chemistry" }, /obj/machinery/door/window/southleft{ - base_state = "left"; dir = 1; - icon_state = "left"; name = "Chemistry"; req_access_txt = "150" }, @@ -1968,9 +1959,7 @@ /area/ruin/unpowered/syndicate_lava_base/virology) "gs" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3{ - dir = 2 - }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3, /obj/machinery/light/small, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel/white, @@ -2153,9 +2142,7 @@ icon_state = "4-8" }, /obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3{ - dir = 2 - }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3, /obj/structure/cable/yellow{ icon_state = "1-8" }, @@ -2864,7 +2851,6 @@ /area/ruin/unpowered/syndicate_lava_base/main) "ib" = ( /obj/effect/mob_spawn/human/lavaland_syndicate{ - icon_state = "sleeper_s"; dir = 4 }, /turf/open/floor/plasteel/grimy, @@ -2904,8 +2890,7 @@ /area/ruin/unpowered/syndicate_lava_base/dormitories) "ie" = ( /obj/effect/mob_spawn/human/lavaland_syndicate/comms{ - dir = 8; - icon_state = "sleeper_s" + dir = 8 }, /turf/open/floor/plasteel/grimy, /area/ruin/unpowered/syndicate_lava_base/dormitories) @@ -3029,10 +3014,10 @@ dir = 1 }, /obj/machinery/turretid{ + ailock = 1; control_area = "/area/ruin/unpowered/syndicate_lava_base/main"; dir = 1; icon_state = "control_kill"; - ailock = 1; lethal = 1; name = "Base turret controls"; pixel_y = 30; @@ -3149,7 +3134,6 @@ dir = 1 }, /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer3, @@ -3321,9 +3305,7 @@ "iT" = ( /obj/machinery/light/small, /obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3{ - dir = 2 - }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3, /obj/structure/cable/yellow{ icon_state = "4-8" }, @@ -3356,7 +3338,6 @@ dir = 4 }, /obj/machinery/power/apc/syndicate{ - dir = 2; name = "Dormitories APC"; pixel_y = -24 }, @@ -3565,7 +3546,6 @@ /area/ruin/unpowered/syndicate_lava_base/main) "jn" = ( /obj/effect/mob_spawn/human/lavaland_syndicate{ - icon_state = "sleeper_s"; dir = 4 }, /obj/machinery/airalarm/syndicate{ @@ -3591,8 +3571,7 @@ /area/ruin/unpowered/syndicate_lava_base/main) "jq" = ( /obj/effect/mob_spawn/human/lavaland_syndicate{ - dir = 8; - icon_state = "sleeper_s" + dir = 8 }, /obj/machinery/airalarm/syndicate{ pixel_y = 24 @@ -3986,9 +3965,7 @@ /area/ruin/unpowered/syndicate_lava_base/main) "kd" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3{ - dir = 2 - }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3, /obj/structure/cable/yellow{ icon_state = "1-4" }, @@ -4059,9 +4036,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 9 }, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3{ - dir = 2 - }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/main) "kj" = ( @@ -4247,8 +4222,10 @@ icon_state = "4-8" }, /obj/machinery/atmospherics/pipe/simple/supply/visible, -/obj/machinery/atmospherics/pipe/manifold4w/scrubbers/visible/layer3, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible/layer3{ + dir = 4 + }, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "kA" = ( @@ -4266,11 +4243,9 @@ /obj/structure/cable/yellow{ icon_state = "0-8" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3{ - dir = 9 - }, /obj/machinery/atmospherics/components/unary/vent_pump/on, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "kB" = ( @@ -4285,6 +4260,7 @@ /obj/machinery/computer/atmos_control/tank{ dir = 8; frequency = 1442; + input_tag = "syndie_lavaland_n2_in"; name = "Nitrogen Supply Control"; output_tag = "syndie_lavaland_n2_out"; sensors = list("syndie_lavaland_n2_sensor" = "Tank") @@ -4477,12 +4453,19 @@ /obj/machinery/atmospherics/pipe/simple/supply/visible{ dir = 5 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/n2{ + dir = 1; + piping_layer = 3 + }, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "kY" = ( /obj/machinery/atmospherics/pipe/manifold4w/supply/visible, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3{ + dir = 8 + }, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "kZ" = ( @@ -4490,6 +4473,9 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3{ + dir = 8 + }, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "la" = ( @@ -4503,6 +4489,9 @@ /obj/effect/turf_decal/tile/red{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3{ + dir = 4 + }, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "lb" = ( @@ -4511,6 +4500,9 @@ /obj/machinery/atmospherics/pipe/simple/supplymain/visible{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ + dir = 10 + }, /turf/open/floor/plating, /area/ruin/unpowered/syndicate_lava_base/engineering) "lc" = ( @@ -4523,6 +4515,11 @@ /turf/open/floor/plating/airless, /area/ruin/unpowered/syndicate_lava_base/engineering) "ld" = ( +/obj/machinery/atmospherics/components/unary/outlet_injector/layer3{ + dir = 4; + id = "syndie_lavaland_n2_in"; + piping_layer = 3 + }, /turf/open/floor/plating/airless, /area/ruin/unpowered/syndicate_lava_base/engineering) "le" = ( @@ -4676,15 +4673,24 @@ /turf/open/floor/plating, /area/ruin/unpowered/syndicate_lava_base/engineering) "lr" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3, -/turf/open/floor/plasteel, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ + dir = 10 + }, +/turf/closed/wall/mineral/plastitanium/nodiagonal, /area/ruin/unpowered/syndicate_lava_base/engineering) "ls" = ( /obj/machinery/atmospherics/pipe/simple/supply/visible, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3{ + dir = 8 + }, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "lt" = ( /obj/machinery/atmospherics/pipe/simple/supplymain/visible, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3{ + dir = 4 + }, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "lu" = ( @@ -4694,6 +4700,9 @@ /obj/machinery/portable_atmospherics/scrubber, /obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3{ + dir = 10 + }, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "lv" = ( @@ -4848,29 +4857,33 @@ /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "lM" = ( -/obj/structure/cable{ - icon_state = "1-2" +/obj/machinery/atmospherics/components/unary/outlet_injector/layer3{ + id = "syndie_lavaland_tox_in"; + piping_layer = 3 }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer3{ - dir = 4 - }, -/turf/open/floor/plasteel, +/turf/open/floor/plating/airless, /area/ruin/unpowered/syndicate_lava_base/engineering) "lN" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3{ - dir = 9 +/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/o2{ + dir = 1; + piping_layer = 3 }, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "lO" = ( /obj/machinery/atmospherics/pipe/simple/supply/visible, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3{ + dir = 8 + }, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "lP" = ( /obj/machinery/computer/atmos_control/tank{ dir = 8; frequency = 1442; + input_tag = "syndie_lavaland_o2_in"; name = "Oxygen Supply Control"; output_tag = "syndie_lavaland_o2_out"; sensors = list("syndie_lavaland_o2_sensor" = "Tank") @@ -4879,12 +4892,15 @@ /obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3{ + dir = 5 + }, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "lQ" = ( /obj/machinery/air_sensor{ frequency = 1442; - id_tag = "Syndicate_Construction_o2_sensor" + id_tag = "syndie_lavaland_o2_sensor" }, /turf/open/floor/plating/airless, /area/ruin/unpowered/syndicate_lava_base/engineering) @@ -5083,6 +5099,9 @@ dir = 6 }, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3{ + dir = 5 + }, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "mj" = ( @@ -5093,11 +5112,15 @@ }, /obj/machinery/atmospherics/pipe/simple/supply/visible, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3{ + dir = 9 + }, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "mk" = ( /obj/machinery/atmospherics/pipe/manifold/supplymain/visible, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "ml" = ( @@ -5170,7 +5193,6 @@ /obj/machinery/light/small, /obj/structure/cable/yellow, /obj/machinery/power/apc/syndicate{ - dir = 2; name = "Bar APC"; pixel_y = -24 }, @@ -5297,6 +5319,9 @@ /obj/structure/reagent_dispensers/watertank, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3{ + dir = 5 + }, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "mK" = ( @@ -5304,12 +5329,16 @@ /obj/machinery/computer/atmos_control/tank{ dir = 1; frequency = 1442; + input_tag = "syndie_lavaland_tox_in"; name = "Toxins Supply Control"; output_tag = "syndie_lavaland_tox_out"; sensors = list("syndie_lavaland_tox_sensor" = "Tank") }, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3{ + dir = 4 + }, /turf/open/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) "mM" = ( @@ -5700,9 +5729,7 @@ /area/ruin/unpowered/syndicate_lava_base/arrivals) "nw" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3{ - dir = 2 - }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3, /obj/structure/cable/yellow{ icon_state = "1-4" }, @@ -5998,7 +6025,6 @@ dir = 4 }, /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /obj/structure/cable/yellow{ @@ -6212,7 +6238,6 @@ }, /obj/structure/cable/yellow, /obj/machinery/power/apc/syndicate{ - dir = 2; name = "Telecommunications APC"; pixel_y = -24 }, @@ -6391,7 +6416,6 @@ "oG" = ( /obj/structure/cable, /obj/machinery/power/turbine{ - dir = 2; luminosity = 2 }, /turf/open/floor/engine/vacuum, @@ -6413,6 +6437,21 @@ /obj/structure/sign/departments/chemistry, /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/ruin/unpowered/syndicate_lava_base/testlab) +"pC" = ( +/obj/structure/grille, +/obj/structure/window/plastitanium, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ + dir = 10 + }, +/turf/open/floor/plating, +/area/ruin/unpowered/syndicate_lava_base/engineering) +"qc" = ( +/obj/machinery/atmospherics/pipe/simple/supplymain/visible, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer3{ + dir = 10 + }, +/turf/open/floor/plasteel, +/area/ruin/unpowered/syndicate_lava_base/engineering) "tW" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/closed/wall/mineral/plastitanium/nodiagonal, @@ -6466,12 +6505,29 @@ /obj/effect/mapping_helpers/airlock/cyclelink_helper, /turf/open/floor/plating, /area/ruin/unpowered/syndicate_lava_base/arrivals) +"Gm" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3, +/turf/closed/wall/mineral/plastitanium/nodiagonal, +/area/ruin/unpowered/syndicate_lava_base/engineering) +"Go" = ( +/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/plasma{ + dir = 1; + piping_layer = 3 + }, +/turf/open/floor/plasteel, +/area/ruin/unpowered/syndicate_lava_base/engineering) "IJ" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ dir = 1 }, /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/ruin/unpowered/syndicate_lava_base/engineering) +"KA" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ + dir = 4 + }, +/turf/closed/wall/mineral/plastitanium/nodiagonal, +/area/ruin/unpowered/syndicate_lava_base/engineering) "Lg" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer3{ dir = 4 @@ -6487,6 +6543,12 @@ /obj/effect/decal/cleanable/dirt, /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/ruin/unpowered/syndicate_lava_base/circuits) +"Ng" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ + dir = 9 + }, +/turf/closed/wall/mineral/plastitanium/nodiagonal, +/area/ruin/unpowered/syndicate_lava_base/engineering) "Pa" = ( /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/ruin/unpowered/syndicate_lava_base/circuits) @@ -6520,6 +6582,14 @@ }, /turf/open/floor/engine, /area/ruin/unpowered/syndicate_lava_base/testlab) +"Tt" = ( +/obj/machinery/atmospherics/components/unary/outlet_injector/layer3{ + dir = 4; + id = "syndie_lavaland_o2_in"; + piping_layer = 3 + }, +/turf/open/floor/plating/airless, +/area/ruin/unpowered/syndicate_lava_base/engineering) "TC" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer3{ dir = 4 @@ -6529,6 +6599,24 @@ }, /turf/open/floor/engine, /area/ruin/unpowered/syndicate_lava_base/testlab) +"Vw" = ( +/obj/structure/grille, +/obj/structure/window/plastitanium, +/obj/machinery/atmospherics/pipe/simple/supplymain/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3, +/turf/open/floor/plating, +/area/ruin/unpowered/syndicate_lava_base/engineering) +"Wq" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ + dir = 10 + }, +/turf/closed/wall/mineral/plastitanium/nodiagonal, +/area/ruin/unpowered/syndicate_lava_base/engineering) (1,1,1) = {" aa @@ -8363,7 +8451,7 @@ ju ky kW lq -lM +mh mh mG nd @@ -8412,8 +8500,8 @@ jW kk kz kX -lr lN +Go mi mH ne @@ -8513,13 +8601,13 @@ km kB kZ lt -lt +qc mk mJ ng nF -ld -ju +lM +uB ab ab ab @@ -8569,7 +8657,7 @@ mK kD nG og -ju +KA ab ab ab @@ -8612,14 +8700,14 @@ ab ju kD lb -ju -kD -lb -ju -ju -ju -ju -ju +uB +pC +Vw +Wq +Gm +Gm +Gm +Ng ab ab ab @@ -8662,10 +8750,10 @@ ab ju kE lc -ju +KA lQ mm -ju +KA ab ab ab @@ -8712,10 +8800,10 @@ ab ju kF ld -ju +KA lR -ld -ju +Tt +KA ab ab ab @@ -8761,11 +8849,11 @@ ab ab ju ju +lr +Ng ju -ju -ju -ju -ju +lr +Ng ab ab ab diff --git a/_maps/RandomRuins/SpaceRuins/spacediner.dmm b/_maps/RandomRuins/SpaceRuins/spacediner.dmm new file mode 100644 index 0000000000..21670da9e4 --- /dev/null +++ b/_maps/RandomRuins/SpaceRuins/spacediner.dmm @@ -0,0 +1,2918 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aa" = ( +/turf/template_noop, +/area/template_noop) +"ab" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"ac" = ( +/obj/machinery/door/airlock/external/glass{ + name = "Shuttle Dock" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ad" = ( +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ae" = ( +/obj/structure/lattice, +/turf/open/space/basic, +/area/space/nearstation) +"af" = ( +/obj/structure/lattice, +/turf/template_noop, +/area/space/nearstation) +"ag" = ( +/turf/closed/wall/r_wall, +/area/ruin/space/diner/interior) +"ah" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/external/glass{ + name = "Shuttle Dock" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ai" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 1 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aj" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ak" = ( +/obj/machinery/light/small{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"al" = ( +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"am" = ( +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/machinery/power/solar, +/turf/open/floor/plasteel/solarpanel, +/area/ruin/space/diner/solars) +"an" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"ao" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ap" = ( +/obj/structure/sign/poster/official/pda_ad600{ + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"aq" = ( +/obj/structure/sign/poster/official/nanotrasen_logo{ + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ar" = ( +/obj/structure/sign/poster/official/cohiba_robusto_ad{ + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"as" = ( +/obj/machinery/firealarm{ + dir = 1; + pixel_y = -24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"at" = ( +/obj/structure/cable, +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/machinery/power/solar, +/turf/open/floor/plasteel/solarpanel, +/area/ruin/space/diner/solars) +"au" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"av" = ( +/turf/open/floor/plating/airless, +/area/ruin/space/diner) +"aw" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 4 + }, +/turf/open/floor/plating/airless, +/area/ruin/space/diner) +"ax" = ( +/turf/closed/wall/r_wall, +/area/ruin/space/diner) +"ay" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/airalarm/all_access{ + dir = 4; + icon_state = "alarm0"; + pixel_x = -24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"az" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/vending/coffee, +/obj/effect/turf_decal/bot, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"aA" = ( +/obj/effect/decal/cleanable/cobweb, +/turf/open/floor/plating{ + icon_state = "platingdmg1" + }, +/area/ruin/space/diner/interior) +"aB" = ( +/obj/structure/reagent_dispensers/beerkeg, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aC" = ( +/obj/structure/table/reinforced, +/obj/machinery/light/small{ + dir = 1 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aD" = ( +/obj/structure/kitchenspike, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aE" = ( +/obj/structure/closet/crate, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aF" = ( +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/structure/closet/crate/freezer, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aG" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/template_noop, +/area/ruin/space/diner/solars) +"aH" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/template_noop, +/area/ruin/space/diner/solars) +"aI" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/template_noop, +/area/ruin/space/diner/solars) +"aJ" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/template_noop, +/area/ruin/space/diner/solars) +"aK" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/template_noop, +/area/ruin/space/diner/solars) +"aL" = ( +/turf/open/floor/engine/airless, +/area/ruin/space/diner) +"aM" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"aN" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"aO" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/vending/cola/red, +/obj/effect/turf_decal/bot, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"aP" = ( +/obj/machinery/atmospherics/components/unary/tank/air{ + dir = 1 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aQ" = ( +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 10 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aR" = ( +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/ruin/space/diner/interior) +"aS" = ( +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aT" = ( +/obj/structure/cable, +/obj/machinery/power/solar, +/turf/open/floor/plasteel/solarpanel, +/area/ruin/space/diner/solars) +"aU" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/template_noop, +/area/ruin/space/diner/solars) +"aV" = ( +/obj/machinery/door/firedoor, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Fore Docking Area" + }, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"aW" = ( +/obj/machinery/door/firedoor, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Fore Docking Area" + }, +/obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"aX" = ( +/obj/machinery/vending/boozeomat/pubby_maint, +/turf/closed/wall/r_wall, +/area/ruin/space/diner/interior) +"aY" = ( +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"aZ" = ( +/obj/structure/closet/crate/bin, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"ba" = ( +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"bb" = ( +/obj/machinery/gibber, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"bc" = ( +/turf/closed/wall/r_wall/rust, +/area/ruin/space/diner/interior) +"bd" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Fore Pod Bay" + }, +/obj/effect/turf_decal/delivery, +/obj/machinery/door/firedoor/closed, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"be" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel/stairs/old, +/area/ruin/space/diner/interior) +"bf" = ( +/obj/structure/cable{ + icon_state = "2-4" + }, +/turf/closed/wall/r_wall, +/area/ruin/space/diner/interior) +"bg" = ( +/obj/structure/cable{ + icon_state = "1-8" + }, +/turf/closed/wall/r_wall, +/area/ruin/space/diner/interior) +"bh" = ( +/obj/machinery/light/small/broken, +/turf/open/floor/engine/airless, +/area/ruin/space/diner) +"bi" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/structure/reagent_dispensers/fueltank, +/obj/machinery/button{ + pixel_y = -24 + }, +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"bj" = ( +/obj/effect/spawner/structure/window/hollow/reinforced, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"bk" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bl" = ( +/obj/structure/table/reinforced, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/chem_dispenser/drinks/beer, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bm" = ( +/obj/structure/table/reinforced, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/chem_dispenser/drinks, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bn" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/vending/dinnerware, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bo" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/secure_closet/freezer/kitchen{ + req_access = null; + req_access_txt = "200" + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bp" = ( +/obj/structure/table/reinforced, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small{ + dir = 1 + }, +/obj/item/reagent_containers/food/condiment/flour, +/obj/item/kitchen/rollingpin, +/obj/item/reagent_containers/food/condiment/rice{ + pixel_x = -8; + pixel_y = 8 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bq" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/processor, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"br" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/firealarm{ + pixel_y = 24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bs" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/sink/kitchen{ + pixel_y = 28 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bt" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/machinery/grill, +/obj/machinery/light/small/broken{ + icon_state = "bulb-broken"; + dir = 1 + }, +/obj/machinery/power/apc/highcap/five_k{ + name = "Space Diner APC"; + pixel_y = 24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bu" = ( +/obj/machinery/deepfryer, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bv" = ( +/obj/effect/decal/cleanable/cobweb{ + icon_state = "cobweb2" + }, +/obj/structure/table/reinforced, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bw" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/closed/wall/r_wall, +/area/ruin/space/diner/interior) +"bx" = ( +/obj/structure/toilet/secret/low_loot{ + icon_state = "toilet00"; + dir = 4 + }, +/obj/effect/decal/cleanable/cobweb, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/window/eastright, +/turf/open/floor/mineral/titanium/white, +/area/ruin/space/diner/interior) +"by" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/sign/poster/contraband/rebels_unite{ + pixel_y = 32 + }, +/obj/item/reagent_containers/food/urinalcake, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bz" = ( +/obj/structure/urinal{ + pixel_y = 28 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bA" = ( +/obj/effect/decal/cleanable/cobweb{ + icon_state = "cobweb2" + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small{ + dir = 1 + }, +/obj/structure/closet/crate/bin, +/obj/machinery/airalarm/all_access{ + dir = 8; + icon_state = "alarm0"; + pixel_x = 24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bB" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 8 + }, +/obj/structure/cable{ + icon_state = "0-4" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"bC" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/middle, +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/structure/cable{ + icon_state = "0-4" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"bD" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 4 + }, +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"bE" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/firealarm{ + dir = 8; + pixel_x = -24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bF" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/machinery/atmospherics/pipe/manifold/general/hidden{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bG" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bH" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bI" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/grunge/abandoned{ + name = "Staff Entrance" + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bJ" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/manifold/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bK" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 10 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bL" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bM" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bN" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/secure_closet/freezer/meat{ + req_access_txt = "200" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bO" = ( +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/closed/wall/r_wall, +/area/ruin/space/diner/interior) +"bP" = ( +/obj/structure/toilet/secret/low_loot{ + icon_state = "toilet00"; + dir = 4 + }, +/obj/structure/window/reinforced/spawner/north, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/window/eastright, +/turf/open/floor/mineral/titanium/white, +/area/ruin/space/diner/interior) +"bQ" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 6 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bR" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bS" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/sink{ + dir = 4; + pixel_x = 11 + }, +/obj/structure/sign/poster/official/cleanliness{ + pixel_x = 32 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bT" = ( +/obj/structure/rack, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"bU" = ( +/obj/structure/table, +/obj/machinery/light/small{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"bV" = ( +/obj/structure/table, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"bW" = ( +/obj/structure/table, +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/item/storage/toolbox/electrical, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"bX" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 1 + }, +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"bY" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"bZ" = ( +/obj/machinery/icecream_vat, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/airalarm/all_access{ + dir = 4; + icon_state = "alarm0"; + pixel_x = -24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ca" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/manifold/general/hidden{ + icon_state = "manifold-2"; + dir = 8 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cb" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cc" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 10 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cd" = ( +/obj/structure/table/reinforced, +/obj/machinery/microwave{ + pixel_y = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ce" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cf" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/mirror{ + icon_state = "mirror_broke"; + pixel_x = 24 + }, +/obj/structure/sink{ + dir = 4; + pixel_x = 11 + }, +/obj/structure/cable{ + icon_state = "0-8" + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cg" = ( +/obj/structure/sign/warning/vacuum/external{ + pixel_x = -32 + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"ch" = ( +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"ci" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"cj" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end, +/obj/structure/cable, +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"ck" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/holopad, +/obj/effect/turf_decal/bot, +/obj/item/radio/intercom{ + pixel_x = 26 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cl" = ( +/obj/structure/grille/broken, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"cm" = ( +/obj/machinery/light{ + dir = 8; + light_color = "#e8eaff" + }, +/obj/structure/table/wood/bar, +/obj/effect/decal/cleanable/dirt, +/obj/item/reagent_containers/food/snacks/stewedsoymeat, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cn" = ( +/obj/structure/table/wood/bar, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"co" = ( +/obj/structure/table/wood/bar, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/obj/item/trash/plate, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cp" = ( +/obj/structure/table/wood/bar, +/obj/effect/decal/cleanable/dirt, +/obj/item/reagent_containers/food/drinks/drinkingglass, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cq" = ( +/obj/structure/table/wood/bar, +/obj/effect/decal/cleanable/dirt, +/obj/item/reagent_containers/food/condiment/saltshaker{ + pixel_x = 4; + pixel_y = 2 + }, +/obj/item/reagent_containers/food/condiment/peppermill{ + pixel_x = -4; + pixel_y = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cr" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/bot, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/obj/structure/frame, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cs" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/table/wood/bar, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ct" = ( +/obj/machinery/light{ + dir = 4; + light_color = "#e8eaff" + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/table/wood/bar, +/obj/structure/window/reinforced/spawner, +/obj/structure/window/reinforced/spawner/west, +/obj/machinery/dish_drive, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cu" = ( +/obj/structure/sign/barsign, +/turf/closed/wall/r_wall, +/area/ruin/space/diner/interior) +"cv" = ( +/obj/machinery/door/airlock/grunge/abandoned{ + name = "Restrooms" + }, +/obj/machinery/door/firedoor, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cw" = ( +/obj/machinery/airalarm/all_access{ + dir = 1; + icon_state = "alarm0"; + pixel_x = 0; + pixel_y = -24 + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"cx" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/obj/machinery/airalarm/all_access{ + dir = 4; + icon_state = "alarm0"; + pixel_x = -24 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cy" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"cz" = ( +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/obj/item/beacon, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"cA" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"cB" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/public/glass{ + name = "Teleporter Room" + }, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"cC" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cD" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/machinery/atmospherics/pipe/manifold/general/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cE" = ( +/obj/structure/chair/stool/bar, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"cF" = ( +/obj/structure/chair/stool/bar, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"cG" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cH" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cI" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/machinery/computer/slot_machine, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cJ" = ( +/obj/structure/chair{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"cK" = ( +/obj/structure/table/wood, +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/reagent_containers/food/drinks/drinkingglass, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"cL" = ( +/obj/structure/table/wood, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/trash/plate, +/obj/item/kitchen/fork, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"cM" = ( +/obj/machinery/light/broken{ + icon_state = "tube-broken"; + dir = 1 + }, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/chair, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"cN" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cO" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/sign/departments/restroom{ + pixel_y = 32 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cP" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cQ" = ( +/obj/structure/sign/warning/vacuum/external{ + pixel_x = 32; + pixel_y = 32 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"cS" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 1 + }, +/obj/structure/cable, +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"cT" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/crate/bin, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cU" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cV" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/sign/poster/official/report_crimes{ + pixel_y = 32 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cW" = ( +/obj/machinery/door/firedoor, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Diner" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cX" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cY" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"cZ" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 5 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"da" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"db" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/manifold/general/hidden, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dc" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dd" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/general/hidden{ + icon_state = "pipe11-2"; + dir = 9 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"de" = ( +/obj/machinery/door/airlock/external{ + name = "Mining Shuttle Dock" + }, +/obj/machinery/door/firedoor, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"df" = ( +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dg" = ( +/obj/machinery/door/airlock/external/glass, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dh" = ( +/obj/machinery/teleport/hub, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"di" = ( +/obj/machinery/light/small/broken, +/obj/machinery/teleport/station, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"dj" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/computer/teleporter{ + icon_state = "computer"; + dir = 1 + }, +/obj/structure/cable, +/turf/open/floor/plasteel/dark, +/area/ruin/space/diner/interior) +"dk" = ( +/obj/structure/lattice/catwalk, +/turf/template_noop, +/area/space/nearstation) +"dm" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end, +/obj/structure/cable, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dn" = ( +/obj/machinery/light/small, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"do" = ( +/obj/machinery/door/firedoor, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Diner" + }, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dp" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dq" = ( +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dr" = ( +/obj/structure/sign/mining{ + pixel_x = 32 + }, +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/reagent_containers/rag, +/obj/item/kitchen/fork, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"ds" = ( +/obj/structure/cable, +/obj/machinery/power/solar_control{ + icon_state = "computer"; + dir = 4 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dt" = ( +/obj/structure/sign/poster/ripped{ + pixel_x = 32 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dv" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 4 + }, +/obj/structure/cable, +/obj/structure/cable{ + icon_state = "0-8" + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dx" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/manifold/general/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dy" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/machinery/light/broken{ + icon_state = "tube-broken"; + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dz" = ( +/obj/structure/chair, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dA" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/chair, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dB" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dC" = ( +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/chair{ + icon_state = "chair_toppled"; + dir = 1 + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dD" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/reagent_containers/food/snacks/sushi_rice, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dE" = ( +/obj/machinery/light/small/broken{ + icon_state = "bulb-broken"; + dir = 1 + }, +/turf/open/floor/engine/airless, +/area/ruin/space/diner) +"dF" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/button{ + pixel_y = 24 + }, +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"dG" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/machinery/vending/cola/blue, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dH" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/trash/plate, +/obj/item/reagent_containers/food/condiment/pack/ketchup{ + pixel_x = -4 + }, +/obj/item/reagent_containers/food/condiment/pack/mustard{ + pixel_x = 4 + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dI" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/item/trash/plate, +/obj/item/reagent_containers/food/snacks/hotdog, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dJ" = ( +/obj/machinery/light, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dK" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/reagent_containers/food/drinks/bottle/whiskey, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dL" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/trash/plate{ + pixel_y = -2 + }, +/obj/item/reagent_containers/food/snacks/burger/mcguffin, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dM" = ( +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/machinery/jukebox, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dN" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/kitchen/fork, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dO" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/trash/plate, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dP" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dQ" = ( +/obj/machinery/light, +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/reagent_containers/food/drinks/bottle/vodka, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dR" = ( +/obj/structure/table/wood, +/obj/effect/decal/cleanable/dirt{ + desc = "A thin layer of dust coating the floor."; + name = "dust" + }, +/obj/item/reagent_containers/food/drinks/coffee, +/turf/open/floor/carpet, +/area/ruin/space/diner/interior) +"dS" = ( +/obj/item/storage/wallet/random, +/turf/open/floor/engine/airless, +/area/ruin/space/diner) +"dT" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"dU" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Aft Pod Bay" + }, +/obj/effect/turf_decal/delivery, +/obj/machinery/door/firedoor/closed, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"dV" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/directional{ + icon_state = "hrwindow_spawner_directional"; + dir = 10 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dW" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/middle, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dX" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 4 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dY" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 8 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"dZ" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/directional{ + icon_state = "hrwindow_spawner_directional"; + dir = 6 + }, +/turf/open/floor/plating, +/area/ruin/space/diner/interior) +"ea" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/template_noop, +/area/space/nearstation) +"eb" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Aft Docking Area" + }, +/obj/effect/turf_decal/delivery, +/obj/machinery/door/firedoor/closed, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ec" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/public/glass{ + name = "Aft Docking Area" + }, +/obj/effect/turf_decal/delivery, +/obj/machinery/door/firedoor/closed, +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel, +/area/ruin/space/diner/interior) +"ed" = ( +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"ee" = ( +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"ef" = ( +/obj/machinery/light/small/broken{ + icon_state = "bulb-broken"; + dir = 1 + }, +/obj/machinery/vending/snack, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"eg" = ( +/obj/effect/spawner/structure/window/hollow/reinforced/end{ + icon_state = "hrwindow_spawner_end"; + dir = 1 + }, +/turf/open/floor/plating/airless, +/area/ruin/space/diner) +"eh" = ( +/obj/machinery/atmospherics/pipe/simple/general/hidden, +/turf/open/floor/plating/airless, +/area/ruin/space/diner) +"ei" = ( +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel/airless, +/area/ruin/space/diner) +"ej" = ( +/obj/structure/girder/reinforced, +/turf/open/floor/plating/airless, +/area/ruin/space/diner) + +(1,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(2,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(3,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(4,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(5,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +af +af +af +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(6,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +af +dk +dk +dk +af +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(7,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +af +av +ax +af +dk +dk +dk +af +ej +aa +aa +aa +aa +aa +aa +aa +aa +"} +(8,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +av +aL +aL +ag +ag +ag +dg +ag +ag +ag +af +aa +aa +aa +aa +aa +aa +aa +"} +(9,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +af +aL +aL +aL +aL +bB +bT +cg +ch +ch +dh +bB +av +af +aa +aa +aa +aa +aa +aa +"} +(10,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +av +aL +aL +aL +bh +bC +bU +ch +cy +ch +di +bC +dE +aL +af +aa +aa +aa +aa +aa +"} +(11,1,1) = {" +aa +aa +aa +aa +aa +af +aa +aw +aL +aL +aL +aL +bD +bV +ci +cz +ci +dj +dv +aL +dS +av +af +aa +aa +aa +aa +"} +(12,1,1) = {" +aa +aa +aa +aa +af +af +af +ax +aM +aM +aM +bi +ag +bW +ch +cA +ch +cw +ag +dF +dT +av +af +aa +aa +aa +aa +"} +(13,1,1) = {" +aa +aa +aa +ag +ai +an +ag +ag +ag +ag +bd +bj +ag +bX +cj +cB +cS +dm +ag +bj +dU +ag +ax +ax +ej +aa +aa +"} +(14,1,1) = {" +aa +aa +aa +ag +aj +aj +aj +ay +aj +aV +aj +aj +bE +aj +aj +cC +cT +aj +cx +aj +aj +eb +ed +ed +av +aa +aa +"} +(15,1,1) = {" +aa +aa +aa +ag +ak +ao +au +au +aN +aW +au +au +bF +bY +bY +cD +cU +au +dx +au +aN +ec +ee +eh +ed +af +aa +"} +(16,1,1) = {" +aa +ab +ab +ab +al +al +ag +az +aO +ag +ag +bc +bG +aj +ck +aj +bL +dn +ag +ag +ag +ag +ef +ei +af +aa +aa +"} +(17,1,1) = {" +aa +ac +ad +ah +al +ap +ag +ag +ag +ag +ae +ag +bH +ag +ag +ag +cV +aj +ag +af +af +ax +eg +av +aa +aa +aa +"} +(18,1,1) = {" +aa +ab +ab +ab +al +al +ag +aA +aP +aX +ag +ag +bI +ag +cl +ag +cW +do +ag +af +af +aa +aa +af +aa +aa +aa +"} +(19,1,1) = {" +aa +aa +af +ab +al +aq +ag +aB +aQ +aY +be +bk +bJ +ag +ag +ag +cX +cH +ag +ai +dV +aa +aa +af +aa +aa +aa +"} +(20,1,1) = {" +aa +ab +ab +ab +al +al +ag +aC +aR +aZ +ag +bl +bH +bZ +cm +cE +cX +cH +dy +dG +dW +aa +aa +af +aa +aa +aa +"} +(21,1,1) = {" +aa +ac +ad +ah +al +ar +ag +aD +aS +ba +ag +bm +bH +aj +cn +cF +cX +cH +dz +dH +dX +af +af +af +aa +aa +aa +"} +(22,1,1) = {" +aa +ab +ab +ab +al +as +ag +aE +aS +ba +bc +bn +bK +ca +co +cF +cY +dp +dA +dI +bw +ea +ea +ea +aa +aa +aa +"} +(23,1,1) = {" +aa +aa +aa +ag +ak +al +ag +aF +aS +bb +bc +bo +bL +cb +cp +cF +cX +cH +dq +dJ +ag +af +af +af +aa +aa +aa +"} +(24,1,1) = {" +aa +aa +aa +ag +ai +an +ag +ag +ag +bc +ag +bp +bL +cb +cq +cF +cX +cH +dz +dK +dY +aa +aa +af +aa +aa +aa +"} +(25,1,1) = {" +aa +aa +aa +aa +aa +aa +af +af +af +aa +ag +bq +bL +cc +cr +cG +cZ +cH +dz +dL +dW +aa +aa +aa +aa +aa +aa +"} +(26,1,1) = {" +aa +aa +aa +af +am +at +at +aG +aT +af +ag +br +bL +aj +cs +cH +da +cH +dq +dq +dW +aa +af +aa +aa +aa +aa +"} +(27,1,1) = {" +aa +aa +aa +aa +aa +aa +af +aH +af +aa +ag +bs +bL +aj +ct +cH +da +cH +dq +dM +dW +aa +aa +aa +aa +aa +aa +"} +(28,1,1) = {" +aa +aa +aa +af +am +at +at +aI +aT +af +ag +bt +bM +aj +cu +cI +da +cH +dz +dN +dW +aa +aa +aa +aa +aa +aa +"} +(29,1,1) = {" +aa +aa +aa +aa +aa +aa +af +aH +af +aa +bc +bu +bL +aj +ag +cJ +da +cH +dz +dO +dW +aa +aa +aa +af +aa +aa +"} +(30,1,1) = {" +aa +aa +aa +af +am +at +at +aI +aT +af +ag +bv +bN +cd +ag +cK +db +cH +dq +dq +dW +aa +aa +aa +aa +aa +aa +"} +(31,1,1) = {" +aa +aa +aa +aa +aa +aa +af +aH +af +af +bf +bw +bO +bw +bw +cL +dc +cH +dz +dP +dX +aa +aa +af +aa +aa +aa +"} +(32,1,1) = {" +aa +aa +aa +aa +af +am +at +aJ +aU +aU +bg +bx +bP +bP +bc +cM +da +cH +dz +dQ +ag +af +af +af +aa +aa +aa +"} +(33,1,1) = {" +aa +aa +aa +aa +aa +aa +af +aH +af +af +bc +by +bQ +ce +cv +cN +dd +dp +dB +dB +bw +ea +ea +aa +aa +aa +aa +"} +(34,1,1) = {" +aa +aa +aa +aa +aa +af +am +aK +aT +af +ag +bz +bR +bL +ag +cO +cX +dq +dC +dq +dY +af +af +aa +aa +aa +aa +"} +(35,1,1) = {" +aa +aa +aa +aa +aa +aa +af +af +af +aa +ag +bA +bS +cf +ag +cP +cX +dr +dD +dR +dW +aa +aa +aa +aa +aa +aa +"} +(36,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +ag +ag +ag +ag +ag +bc +de +ag +ag +ai +dZ +aa +aa +aa +aa +aa +aa +"} +(37,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +ag +aS +df +ds +ag +aa +aa +aa +aa +aa +aa +aa +aa +"} +(38,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +ag +cQ +aS +dt +ag +af +af +aa +aa +aa +aa +aa +aa +"} +(39,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +af +ag +dg +dg +ag +ag +aa +aa +aa +aa +aa +aa +aa +aa +"} +(40,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} diff --git a/_maps/RandomRuins/SpaceRuinsStation/roid7.dmm b/_maps/RandomRuins/SpaceRuinsStation/roid7.dmm index d694fc7c9f..9cc192efc7 100644 --- a/_maps/RandomRuins/SpaceRuinsStation/roid7.dmm +++ b/_maps/RandomRuins/SpaceRuinsStation/roid7.dmm @@ -168,7 +168,7 @@ /turf/template_noop, /area/template_noop) "H" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/open/floor/plasteel/airless/cafeteria, /area/ruin/space) "I" = ( diff --git a/_maps/RandomZLevels/away_mission/TheBeach.dmm b/_maps/RandomZLevels/away_mission/TheBeach.dmm index cc9f50d029..5430d8dd92 100644 --- a/_maps/RandomZLevels/away_mission/TheBeach.dmm +++ b/_maps/RandomZLevels/away_mission/TheBeach.dmm @@ -799,7 +799,7 @@ /turf/open/floor/wood, /area/awaymission/beach) "cn" = ( -/obj/machinery/vending/boozeomat/all_access{ +/obj/machinery/vending/boozeomat{ desc = "A technological marvel, supposedly able to mix just the mixture you'd like to drink the moment you ask for one. May not work for bartenders that don't have Nanotrasen bank accounts." }, /turf/open/floor/wood, diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index 75efefd8e1..9bda6c7df2 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -3993,8 +3993,6 @@ }, /obj/structure/closet/wardrobe/white, /obj/item/clothing/under/suit/waiter, -/obj/item/clothing/under/suit/waiter, -/obj/item/clothing/under/suit/waiter, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "ahD" = ( @@ -4127,24 +4125,18 @@ /turf/open/floor/plasteel, /area/security/main) "ahO" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 4; - pixel_y = 5 - }, /obj/structure/chair/sofa/left{ dir = 1 }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 4 + }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "ahP" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/closet/wardrobe/mixed, /obj/item/clothing/under/costume/kilt, -/obj/item/clothing/under/costume/kilt, -/obj/item/clothing/under/dress/skirt/purple, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/beret, /obj/structure/sign/poster/official/fashion{ pixel_x = -32 }, @@ -4675,13 +4667,13 @@ /turf/open/floor/plating, /area/maintenance/fore/secondary) "aiB" = ( -/obj/machinery/vending/kink, /obj/structure/disposalpipe/segment{ dir = 4 }, /obj/structure/sign/poster/official/fashion{ pixel_y = 32 }, +/obj/machinery/vending/autodrobe, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aiC" = ( @@ -10717,21 +10709,7 @@ /obj/structure/closet{ name = "Holodeck Outfits" }, -/obj/item/clothing/under/trek/Q, -/obj/item/clothing/under/trek/command/next, -/obj/item/clothing/under/trek/command/next, -/obj/item/clothing/under/trek/command/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/medsci/next, -/obj/item/clothing/under/trek/medsci/next, -/obj/item/clothing/under/trek/medsci/next, /obj/item/clothing/under/misc/blue_camo, -/obj/item/clothing/under/misc/blue_camo, -/obj/item/clothing/under/costume/gladiator, -/obj/item/clothing/under/costume/gladiator, /obj/machinery/firealarm{ dir = 4; pixel_x = -24 @@ -13940,8 +13918,7 @@ /area/crew_quarters/dorms) "aFk" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 4; - pixel_y = 5 + dir = 4 }, /turf/open/floor/wood, /area/crew_quarters/bar) @@ -14441,13 +14418,12 @@ /turf/closed/wall, /area/crew_quarters/theatre) "aGw" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 4; - pixel_y = 5 - }, /obj/machinery/light/small{ dir = 4 }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, /turf/open/floor/wood, /area/crew_quarters/bar) "aGx" = ( @@ -15098,10 +15074,6 @@ /turf/open/floor/plasteel, /area/crew_quarters/dorms) "aHV" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 1; - pixel_x = 5 - }, /obj/machinery/light/small{ dir = 4 }, @@ -15114,6 +15086,9 @@ /obj/item/reagent_containers/rag/towel/random, /obj/item/reagent_containers/rag/towel/random, /obj/item/reagent_containers/rag/towel/random, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, /turf/open/floor/mineral/titanium/blue, /area/crew_quarters/toilet) "aHY" = ( @@ -16721,10 +16696,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/structure/sign/poster/contraband/robust_softdrinks{ - pixel_x = -32; - pixel_y = 32 - }, /turf/open/floor/plasteel, /area/hallway/primary/central) "aMh" = ( @@ -17947,7 +17918,6 @@ /obj/structure/cable{ icon_state = "0-8" }, -/obj/machinery/status_display/evac, /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/preopen{ id = "bridge blast"; @@ -17972,21 +17942,6 @@ }, /turf/open/floor/plating, /area/bridge) -"aPW" = ( -/obj/structure/cable{ - icon_state = "0-8" - }, -/obj/structure/cable{ - icon_state = "0-4" - }, -/obj/machinery/status_display/evac, -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/door/poddoor/preopen{ - id = "bridge blast"; - name = "bridge blast door" - }, -/turf/open/floor/plating, -/area/bridge) "aPX" = ( /obj/structure/cable{ icon_state = "0-8" @@ -18310,7 +18265,6 @@ /obj/structure/closet/wardrobe/white, /obj/item/clothing/suit/ghost_sheet, /obj/item/clothing/suit/ghost_sheet, -/obj/item/clothing/suit/ghost_sheet, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQP" = ( @@ -18338,10 +18292,10 @@ /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQV" = ( -/obj/machinery/vending/autodrobe/all_access, /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/machinery/vending/clothing, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQW" = ( @@ -18355,7 +18309,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/machinery/vending/games, +/obj/machinery/vending/kink, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQY" = ( @@ -18838,9 +18792,6 @@ name = "Station Intercom (General)"; pixel_x = -27 }, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/russobluecamohat, /obj/item/clothing/head/russobluecamohat, /turf/open/floor/plasteel, /area/crew_quarters/locker) @@ -19161,6 +19112,7 @@ /obj/structure/cable{ icon_state = "4-8" }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plating, /area/maintenance/port) "aSY" = ( @@ -19323,7 +19275,6 @@ dir = 8 }, /obj/item/clothing/under/costume/kilt, -/obj/item/clothing/under/costume/kilt, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aTy" = ( @@ -19841,11 +19792,6 @@ department = "Locker Room"; pixel_x = -32 }, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/color/grey, -/obj/item/clothing/under/color/grey, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aUW" = ( @@ -20456,13 +20402,6 @@ "aWn" = ( /obj/structure/closet/wardrobe/black, /obj/item/clothing/shoes/jackboots, -/obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/under/costume/maid, -/obj/item/clothing/under/costume/maid, -/obj/item/clothing/accessory/maidapron, -/obj/item/clothing/accessory/maidapron, -/obj/item/clothing/head/beret/black, /obj/item/clothing/head/beret/black, /turf/open/floor/plasteel, /area/crew_quarters/locker) @@ -21811,12 +21750,10 @@ dir = 4; pixel_x = 11 }, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 1 - }, /obj/structure/mirror{ pixel_x = 28 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "aZp" = ( @@ -21889,6 +21826,7 @@ /area/crew_quarters/toilet/locker) "aZw" = ( /obj/effect/landmark/blobstart, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "aZx" = ( @@ -22247,6 +22185,7 @@ c_tag = "Locker Room Toilets"; dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "bax" = ( @@ -22381,13 +22320,6 @@ /area/maintenance/port) "baO" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/structure/sink{ - dir = 4; - pixel_x = 11 - }, -/obj/structure/mirror{ - pixel_x = 28 - }, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "baP" = ( @@ -22573,9 +22505,7 @@ /obj/machinery/light{ dir = 8 }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 1 - }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "bbs" = ( @@ -22942,9 +22872,8 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard) "bct" = ( -/obj/structure/chair/wood/wings, -/turf/open/floor/plating, -/area/maintenance/port) +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "bcu" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/door/airlock/maintenance{ @@ -23421,9 +23350,12 @@ /turf/open/floor/carpet, /area/bridge/meeting_room) "bdJ" = ( -/obj/structure/closet/secure_closet/personal/cabinet, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/door/airlock{ + id_tag = "LockerShitter3"; + name = "Unit 3" + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "bdK" = ( /obj/machinery/holopad, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -23440,6 +23372,7 @@ dir = 8 }, /obj/structure/bedsheetbin/color, +/obj/structure/table, /turf/open/floor/plasteel/cafeteria, /area/crew_quarters/locker) "bdN" = ( @@ -23989,13 +23922,6 @@ }, /turf/closed/wall, /area/maintenance/disposal) -"bfa" = ( -/obj/structure/closet/crate, -/obj/item/stack/sheet/mineral/wood/fifty{ - amount = 20 - }, -/turf/open/floor/plating, -/area/maintenance/port) "bfb" = ( /obj/structure/sign/warning/vacuum/external{ pixel_y = 32 @@ -24471,14 +24397,12 @@ /turf/open/floor/plating, /area/maintenance/port) "bgr" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on, -/turf/open/floor/plating, -/area/maintenance/port) -"bgs" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/obj/structure/table/wood/fancy/purple, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/door/airlock{ + id_tag = "LockerShitter4"; + name = "Unit 4" + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "bgt" = ( /obj/effect/spawner/lootdrop/maintenance, /turf/open/floor/plating, @@ -24736,9 +24660,6 @@ /obj/machinery/camera{ c_tag = "Chemistry" }, -/obj/machinery/firealarm{ - pixel_y = 24 - }, /obj/machinery/chem_heater, /turf/open/floor/plasteel/white, /area/medical/chemistry) @@ -25096,7 +25017,7 @@ dir = 4 }, /turf/closed/wall, -/area/maintenance/port) +/area/crew_quarters/toilet/locker) "bhR" = ( /obj/structure/grille, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -27778,6 +27699,10 @@ /obj/machinery/light{ dir = 8 }, +/obj/machinery/firealarm{ + dir = 4; + pixel_x = -26 + }, /turf/open/floor/plasteel/white, /area/medical/chemistry) "boc" = ( @@ -29238,14 +29163,7 @@ /turf/open/floor/plating, /area/maintenance/starboard) "brz" = ( -/obj/structure/table, -/obj/item/pen, -/obj/machinery/camera{ - c_tag = "Experimentor Lab"; - network = list("ss13","rd") - }, -/obj/item/hand_labeler, -/obj/item/stack/packageWrap, +/obj/machinery/rnd/bepis, /turf/open/floor/plasteel/white/side, /area/science/explab) "brA" = ( @@ -29262,11 +29180,14 @@ "brC" = ( /obj/structure/table, /obj/item/folder/white, -/obj/item/folder/white, /obj/machinery/airalarm{ pixel_y = 23 }, /obj/item/radio/off, +/obj/machinery/camera{ + c_tag = "Experimentor Lab"; + network = list("ss13","rd") + }, /turf/open/floor/plasteel/white/side, /area/science/explab) "brD" = ( @@ -38199,7 +38120,7 @@ /obj/machinery/light/small{ dir = 8 }, -/obj/machinery/chem_dispenser, +/obj/machinery/chem_dispenser/apothecary, /turf/open/floor/plasteel/white, /area/medical/medbay/central) "bLV" = ( @@ -41478,13 +41399,6 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) -"bUO" = ( -/obj/machinery/portable_atmospherics/canister, -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "bUR" = ( /obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel, @@ -47925,8 +47839,6 @@ "clO" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/closet/wardrobe/grey, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/misc/assistantformal, /obj/machinery/camera{ c_tag = "Dorms East - Holodeck"; dir = 4 @@ -48962,8 +48874,8 @@ "cpn" = ( /obj/machinery/light, /obj/effect/turf_decal/stripes/line, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 1 }, /turf/open/floor/plasteel, /area/engine/engine_smes) @@ -51988,24 +51900,15 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard) "cBn" = ( -/obj/structure/closet, -/obj/item/stack/tile/carpet/royalblue{ - amount = 24 +/obj/structure/sink{ + dir = 4; + pixel_x = 11 }, -/obj/item/stack/tile/carpet/green{ - amount = 24 +/obj/structure/mirror{ + pixel_x = 28 }, -/obj/item/stack/tile/carpet/purple{ - amount = 24 - }, -/obj/item/stack/tile/carpet/orange{ - amount = 24 - }, -/obj/item/stack/tile/wood{ - amount = 24 - }, -/turf/open/floor/plating, -/area/maintenance/port) +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "cBo" = ( /obj/effect/landmark/event_spawn, /turf/open/floor/wood, @@ -52475,6 +52378,19 @@ /obj/structure/closet/boxinggloves, /turf/open/floor/plasteel, /area/crew_quarters/fitness) +"cFG" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/obj/structure/sink{ + dir = 4; + pixel_x = 11 + }, +/obj/structure/mirror{ + pixel_x = 28 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "cGz" = ( /obj/structure/table/wood, /obj/item/instrument/violin, @@ -52863,10 +52779,6 @@ }, /turf/open/floor/plasteel/airless/solarpanel, /area/solar/starboard/aft) -"cMS" = ( -/obj/item/chair/wood, -/turf/open/floor/plating, -/area/maintenance/port) "cNa" = ( /obj/structure/cable, /obj/machinery/power/solar{ @@ -53845,6 +53757,10 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/security/range) +"dZm" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/closed/wall, +/area/storage/art) "eaI" = ( /obj/structure/table/reinforced, /obj/item/radio/intercom{ @@ -53924,14 +53840,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall, /area/security/execution/transfer) -"epC" = ( -/obj/machinery/door/airlock{ - desc = "To keep the station within regulations, space IKEA requires one storage cupboard for their Nanotrasen partnership to continue."; - id_tag = "MaintDorm1"; - name = "Furniture Storage" - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) "epD" = ( /obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden, /obj/machinery/light{ @@ -54655,10 +54563,6 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/fore) -"gfr" = ( -/obj/structure/bed, -/turf/open/floor/plating, -/area/maintenance/port) "gfC" = ( /obj/effect/turf_decal/tile/red, /obj/structure/chair{ @@ -54912,17 +54816,28 @@ /area/crew_quarters/fitness) "gQX" = ( /obj/machinery/button/door{ - desc = "Alright, GAMER! Want to take your PWRGAME addiction to the MAX? Just smash this button with your chubby chetto encrusted hands an- oh, you broke the switch. Good job, idiot."; - id = "RIPFUN"; - name = "Powerful Gamer Toggle"; + id = "LockerShitter4"; + name = "Door Bolt Control"; normaldoorcontrol = 1; - pixel_x = -24; - pixel_y = 7; + pixel_x = 14; + pixel_y = 38; specialfunctions = 4 }, -/obj/structure/table_frame/wood, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/structure/toilet/secret/low_loot{ + dir = 4 + }, +/obj/machinery/light/small{ + dir = 8 + }, +/obj/structure/sink{ + dir = 1; + pixel_y = 25 + }, +/obj/structure/mirror{ + pixel_y = 32 + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "gRZ" = ( /obj/structure/bookcase{ name = "Forbidden Knowledge" @@ -55000,16 +54915,6 @@ /obj/effect/turf_decal/tile/blue, /turf/open/floor/plasteel, /area/crew_quarters/fitness) -"hew" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/turf/open/floor/plating, -/area/maintenance/port) "hgG" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/structure/extinguisher_cabinet{ @@ -55047,10 +54952,6 @@ }, /turf/closed/wall, /area/crew_quarters/dorms) -"hnl" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, -/turf/closed/wall, -/area/maintenance/port) "hnU" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -55145,21 +55046,18 @@ /turf/open/floor/wood, /area/crew_quarters/bar) "hPs" = ( -/obj/structure/fireplace{ - pixel_y = -6 - }, /obj/machinery/airalarm{ dir = 8; pixel_x = 23 }, -/turf/open/floor/plating, -/area/maintenance/port) +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "hPP" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 8 }, /turf/closed/wall, /area/quartermaster/warehouse) @@ -55361,21 +55259,6 @@ /obj/effect/turf_decal/tile/green, /turf/open/floor/plasteel, /area/hallway/primary/starboard) -"ivJ" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible, -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/layer_manifold{ - dir = 4 - }, -/turf/open/floor/plating, -/area/engine/atmos) -"iwB" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/closed/wall, -/area/maintenance/port) "izg" = ( /obj/item/cigbutt/cigarbutt, /turf/open/floor/plating, @@ -55617,9 +55500,7 @@ }, /area/maintenance/bar) "jrE" = ( -/obj/structure/sign/poster/official/random{ - pixel_x = 32 - }, +/obj/item/beacon, /turf/open/floor/plasteel/white, /area/science/circuit) "jtj" = ( @@ -56003,6 +55884,10 @@ /area/maintenance/fore/secondary) "khV" = ( /obj/machinery/vending/cola/red, +/obj/structure/sign/poster/contraband/robust_softdrinks{ + pixel_x = -32; + pixel_y = 32 + }, /turf/open/floor/plasteel/dark, /area/hallway/primary/central) "kls" = ( @@ -56289,10 +56174,6 @@ }, /turf/open/floor/plasteel, /area/security/brig) -"kQO" = ( -/obj/structure/reagent_dispensers/keg/semen, -/turf/open/floor/plating, -/area/maintenance/bar) "kSb" = ( /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, @@ -56424,7 +56305,7 @@ }, /area/maintenance/bar) "lsk" = ( -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/kink, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "ltK" = ( @@ -57356,17 +57237,29 @@ /turf/open/floor/plasteel, /area/security/prison) "omY" = ( -/obj/item/flashlight/lamp/green{ - pixel_x = -2; - pixel_y = 15 +/obj/machinery/button/door{ + id = "LockerShitter3"; + name = "Door Bolt Control"; + normaldoorcontrol = 1; + pixel_x = 14; + pixel_y = 38; + specialfunctions = 4 }, -/obj/structure/dresser{ - desc = "There's plenty of clothes here to change into! It has a surprising amount of variety, too."; - name = "Dresser"; - pixel_y = 7 +/obj/structure/toilet/secret/low_loot{ + dir = 4 }, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/light/small{ + dir = 8 + }, +/obj/structure/sink{ + dir = 1; + pixel_y = 25 + }, +/obj/structure/mirror{ + pixel_y = 32 + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "oqj" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -57586,12 +57479,7 @@ "oZl" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/closet/wardrobe/pjs, -/obj/item/clothing/under/costume/maid, -/obj/item/clothing/under/costume/maid, /obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/accessory/maidapron, -/obj/item/clothing/accessory/maidapron, /obj/machinery/light{ dir = 8 }, @@ -57635,6 +57523,9 @@ /obj/machinery/door/airlock/maintenance{ req_access_txt = "12" }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/wood, /area/crew_quarters/bar) "plS" = ( @@ -57685,7 +57576,6 @@ /turf/open/floor/wood, /area/crew_quarters/bar) "pqs" = ( -/obj/machinery/vending/clothing, /obj/structure/disposalpipe/segment{ dir = 4 }, @@ -58181,11 +58071,11 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/machinery/vending/kink, /obj/machinery/light{ dir = 4; light_color = "#e8eaff" }, +/obj/machinery/vending/games, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "rgL" = ( @@ -58287,11 +58177,6 @@ dir = 4 }, /obj/structure/closet/wardrobe/black, -/obj/item/clothing/under/dress/skirt, -/obj/item/clothing/head/beret/black, -/obj/item/clothing/head/beret/black, -/obj/item/clothing/under/custom/trendy_fit, -/obj/item/clothing/under/custom/trendy_fit, /obj/item/clothing/under/dress/sundress, /turf/open/floor/plasteel, /area/crew_quarters/fitness) @@ -58460,6 +58345,10 @@ }, /turf/open/floor/plasteel, /area/science/mixing) +"rNG" = ( +/obj/machinery/status_display/evac, +/turf/closed/wall, +/area/ai_monitored/storage/eva) "rPU" = ( /turf/open/floor/plasteel/white/side{ dir = 4 @@ -58873,7 +58762,7 @@ /turf/open/floor/plating, /area/maintenance/fore/secondary) "sXA" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/closed/wall, /area/maintenance/bar) "sXV" = ( @@ -58986,11 +58875,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/crew_quarters/dorms) -"txm" = ( -/obj/structure/table/wood/fancy/royalblue, -/obj/item/crowbar/red, -/turf/open/floor/plating, -/area/maintenance/port) "tyX" = ( /obj/structure/cable{ icon_state = "4-8" @@ -59535,11 +59419,10 @@ /turf/open/floor/plasteel, /area/engine/atmos) "uQS" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 1; - pixel_x = 5 - }, /obj/machinery/light/small, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 1 + }, /turf/open/floor/mineral/titanium/blue, /area/crew_quarters/toilet) "uRd" = ( @@ -60286,6 +60169,12 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) +"wTk" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 1 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "wUg" = ( /obj/effect/turf_decal/stripes/line{ dir = 10 @@ -60888,6 +60777,10 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating, /area/maintenance/fore/secondary) +"yeA" = ( +/obj/machinery/status_display/evac, +/turf/closed/wall, +/area/hallway/primary/central) "yhx" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 5 @@ -77218,10 +77111,10 @@ aXQ aXQ aXQ aXQ -aPz -aPz -epC -aPz +aXQ +aXQ +aXQ +aXQ bhQ bjj bkF @@ -77475,9 +77368,9 @@ aXQ aZt aXQ ycd -aPz +aXQ omY -cMS +aXQ gQX bhQ bjj @@ -77732,12 +77625,12 @@ aXQ aZv aXQ bbL -aPz +aXQ bdJ -txm +aXQ bgr -iwB -hew +bhQ +bjj bkF aaa aaa @@ -77989,10 +77882,10 @@ aWy aYe bbq aZw -aPz +wTk +bct +bct bct -bfa -gfr bhQ bjk bkE @@ -78246,11 +78139,11 @@ aXp baO aZo baw -aPz +cFG hPs cBn -bgs -hnl +bct +bhQ bjk bkF aaa @@ -78503,10 +78396,10 @@ aXQ aXQ aXQ aXQ -aPz -aPz -aPz -aPz +aXQ +aXQ +aXQ +aXQ bhQ bjk aPz @@ -79029,7 +78922,7 @@ blW blW bqi cyD -blW +aZE cyD bvS blW @@ -81581,7 +81474,7 @@ aPF aQZ aRa aTF -aPG +dZm aSX hPP aZF @@ -82660,7 +82553,7 @@ mrR dKP odx rBq -kQO +evR bCq bUs bLv @@ -87998,7 +87891,7 @@ ayL ayW ayW ayW -ayW +rNG aJq aJq aOE @@ -90572,7 +90465,7 @@ aKF aMf aNB aOE -aPW +aPS aRr aSD ceh @@ -91596,7 +91489,7 @@ gfD woR dgz aJw -aJw +yeA aMh aJq aOE @@ -93957,7 +93850,7 @@ bMQ bRC rdl daq -bUO +bUN bOd bOd bOd @@ -94214,7 +94107,7 @@ cBF bRD rdl daq -bUO +bUN bOd bOd bOd @@ -94471,7 +94364,7 @@ bQs cez ceA daq -bUO +bUN bOd bOd bOd @@ -96008,19 +95901,19 @@ bKH bLK bLK bOf -ivJ +bPh bQy bRI bSP -ivJ +bPh jzM bRI cCF -ivJ +bPh bQy bRI bQy -ivJ +bPh bQy bRI bSP diff --git a/_maps/map_files/CogStation/CogStation.dmm b/_maps/map_files/CogStation/CogStation.dmm index ebb3493a35..d2443f076c 100644 --- a/_maps/map_files/CogStation/CogStation.dmm +++ b/_maps/map_files/CogStation/CogStation.dmm @@ -17073,7 +17073,7 @@ /area/security/brig) "aLl" = ( /obj/effect/turf_decal/delivery, -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /turf/open/floor/plasteel, /area/hallway/primary/port/fore) "aLm" = ( @@ -28450,7 +28450,7 @@ /turf/open/floor/plasteel, /area/quartermaster/warehouse) "bjN" = ( -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/quartermaster/office) @@ -72017,6 +72017,10 @@ }, /turf/open/space/basic, /area/space/nearstation) +"mBP" = ( +/obj/machinery/rnd/bepis, +/turf/open/floor/plasteel/white, +/area/science/circuit) "mEa" = ( /obj/machinery/atmospherics/pipe/manifold/cyan/visible, /obj/machinery/meter, @@ -72362,6 +72366,9 @@ /obj/item/pen, /turf/open/floor/plasteel, /area/engine/atmos) +"xxP" = ( +/turf/closed/wall, +/area/quartermaster/storage) "xCy" = ( /obj/machinery/atmospherics/components/binary/pump, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ @@ -93369,7 +93376,7 @@ aTE bTG aVF cGs -aVF +mBP caw caA cHk @@ -121108,7 +121115,7 @@ bgT bjr bkr ble -bgT +xxP bnC boD bgT diff --git a/_maps/map_files/CogStation/FOLDER.txt b/_maps/map_files/CogStation/FOLDER.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 02e44d0a5a..40f05e974c 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -11361,7 +11361,7 @@ "ayW" = ( /obj/machinery/light/small, /obj/effect/decal/cleanable/dirt, -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -14150,10 +14150,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/quartermaster/storage) -"aEh" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/quartermaster/storage) "aEi" = ( /obj/structure/cable/white{ icon_state = "0-2" @@ -15901,9 +15897,6 @@ /turf/open/floor/plasteel/dark, /area/maintenance/disposal/incinerator) "aGU" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 6 - }, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -15918,9 +15911,6 @@ /turf/open/floor/plasteel/dark, /area/maintenance/disposal/incinerator) "aGV" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 10 - }, /obj/structure/cable/white{ icon_state = "2-4" }, @@ -16807,17 +16797,18 @@ /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) "aIu" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible, /obj/structure/cable{ icon_state = "4-8" }, /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/machinery/atmospherics/pipe/simple/general/visible{ + dir = 6 + }, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) "aIv" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible, /obj/structure/cable{ icon_state = "4-8" }, @@ -16828,6 +16819,9 @@ /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/machinery/atmospherics/pipe/simple/general/visible{ + dir = 10 + }, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) "aIw" = ( @@ -18423,10 +18417,10 @@ /obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 4 }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, /turf/open/floor/plasteel/dark/corner, /area/maintenance/disposal/incinerator) "aLi" = ( @@ -18440,26 +18434,15 @@ "aLj" = ( /obj/machinery/meter, /obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/manifold/general/visible, /obj/effect/turf_decal/tile/yellow{ dir = 8 }, -/turf/open/floor/plasteel/dark/corner, -/area/maintenance/disposal/incinerator) -"aLk" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 8; - name = "Port to Turbine" - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 +/obj/machinery/atmospherics/pipe/manifold/general/visible{ + dir = 4 }, /turf/open/floor/plasteel/dark/corner, /area/maintenance/disposal/incinerator) "aLl" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 10 - }, /obj/effect/turf_decal/tile/yellow{ dir = 8 }, @@ -19961,13 +19944,15 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 8 }, /obj/machinery/embedded_controller/radio/airlock_controller/incinerator_atmos{ pixel_y = 27 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 5 + }, /turf/open/floor/engine, /area/maintenance/disposal/incinerator) "aNV" = ( @@ -20022,7 +20007,6 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -20033,6 +20017,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/dark, /area/engine/atmos) "aOa" = ( @@ -20053,7 +20038,6 @@ /area/engine/atmos) "aOb" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/general/visible, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, @@ -20096,9 +20080,6 @@ name = "Station Intercom"; pixel_y = 26 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 6 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -20112,7 +20093,7 @@ /turf/open/floor/plasteel/dark, /area/engine/atmos) "aOe" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, /obj/effect/turf_decal/tile/neutral{ @@ -20125,12 +20106,10 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/general/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) "aOf" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 4 - }, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/engine/atmos) @@ -20141,9 +20120,6 @@ /obj/machinery/light/small{ dir = 1 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 4 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -20157,9 +20133,6 @@ /turf/open/floor/plasteel/dark, /area/engine/atmos) "aOj" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 4 - }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -20177,16 +20150,10 @@ /obj/structure/cable/white{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 4 - }, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/engine/atmos) "aOl" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 4 - }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -20204,9 +20171,6 @@ /obj/machinery/light{ dir = 1 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 10 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -21035,9 +20999,6 @@ /turf/open/floor/plasteel/dark/corner, /area/maintenance/disposal/incinerator) "aPD" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 5 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -21048,6 +21009,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 5 + }, /turf/open/floor/plasteel/dark, /area/engine/atmos) "aPE" = ( @@ -21061,15 +21025,15 @@ /obj/structure/table/reinforced, /obj/item/paper_bin, /obj/item/pen, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/dark/corner{ dir = 1 }, @@ -21080,10 +21044,11 @@ pixel_y = 1 }, /obj/structure/tank_dispenser, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +/obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/obj/effect/turf_decal/tile/yellow{ +/obj/machinery/atmospherics/pipe/simple/general/visible, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, /turf/open/floor/plasteel/dark/corner{ @@ -21096,10 +21061,10 @@ pixel_y = 1 }, /obj/machinery/computer/atmos_control, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +/obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/obj/effect/turf_decal/tile/yellow{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, /turf/open/floor/plasteel/dark/corner{ @@ -21112,11 +21077,10 @@ pixel_y = 1 }, /obj/machinery/computer/atmos_alert, -/obj/machinery/atmospherics/pipe/simple/general/visible, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +/obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/obj/effect/turf_decal/tile/yellow{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, /turf/open/floor/plasteel/dark/corner{ @@ -21132,10 +21096,10 @@ /obj/item/crowbar/red, /obj/item/wrench, /obj/item/clothing/mask/gas, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +/obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/obj/effect/turf_decal/tile/yellow{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, /turf/open/floor/plasteel/dark/corner{ @@ -21159,16 +21123,19 @@ /obj/structure/window/reinforced{ dir = 4 }, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ +/obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/obj/effect/turf_decal/tile/yellow{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, /turf/open/floor/plasteel/checker, /area/engine/atmos) "aPL" = ( /obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "aPM" = ( @@ -21184,15 +21151,15 @@ /obj/item/electronics/airalarm, /obj/item/electronics/firealarm, /obj/item/electronics/firealarm, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 - }, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 1 + }, /turf/open/floor/plasteel/dark/corner{ dir = 1 }, @@ -21265,7 +21232,6 @@ dir = 8 }, /obj/structure/table/reinforced, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/item/stack/rods{ amount = 23 }, @@ -22130,9 +22096,6 @@ /turf/open/floor/plating, /area/maintenance/disposal/incinerator) "aRq" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 6 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -22143,6 +22106,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 6 + }, /turf/open/floor/plasteel/dark, /area/engine/atmos) "aRr" = ( @@ -22173,6 +22139,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 9 }, +/obj/machinery/atmospherics/pipe/simple/general/visible, /turf/open/floor/plasteel, /area/engine/atmos) "aRt" = ( @@ -22187,15 +22154,21 @@ /turf/open/floor/plasteel, /area/engine/atmos) "aRu" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 - }, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/general/visible, -/obj/effect/turf_decal/stripes/line{ +/obj/item/twohanded/required/kirbyplants/random, +/obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/turf/open/floor/plasteel, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, /area/engine/atmos) "aRv" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible{ @@ -22210,11 +22183,7 @@ /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plasteel, +/turf/closed/wall/r_wall, /area/engine/atmos) "aRx" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible{ @@ -22265,7 +22234,6 @@ /obj/machinery/light{ dir = 1 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/effect/turf_decal/stripes/line{ dir = 1 }, @@ -22288,9 +22256,6 @@ /turf/open/floor/plasteel/dark, /area/engine/atmos) "aRD" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 10 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -22301,6 +22266,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/engine/atmos) "aRE" = ( @@ -23222,7 +23190,6 @@ /turf/open/space, /area/space/nearstation) "aST" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -23233,6 +23200,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) "aSU" = ( @@ -23246,15 +23214,19 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, -/turf/open/floor/plasteel/checker, -/area/engine/atmos) -"aSV" = ( /obj/machinery/atmospherics/pipe/simple/yellow/visible{ dir = 6 }, +/turf/open/floor/plasteel/checker, +/area/engine/atmos) +"aSV" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/general/visible, /turf/open/floor/plasteel, /area/engine/atmos) "aSW" = ( @@ -23278,10 +23250,6 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1; - name = "Port to Turbine" - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -23295,24 +23263,11 @@ /turf/open/floor/plasteel, /area/engine/atmos) "aSY" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 4 +/obj/structure/lattice, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 10 }, -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1; - name = "Port to Filter" - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, +/turf/open/space, /area/engine/atmos) "aSZ" = ( /obj/machinery/atmospherics/pipe/simple/yellow/visible{ @@ -23378,7 +23333,6 @@ /obj/structure/cable/white{ icon_state = "2-8" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -23392,13 +23346,12 @@ /turf/open/floor/plasteel, /area/engine/atmos) "aTd" = ( -/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ - dir = 1 - }, -/obj/machinery/meter, /obj/effect/turf_decal/stripes/line{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "aTe" = ( @@ -23409,17 +23362,16 @@ dir = 1; pixel_y = 1 }, -/obj/machinery/atmospherics/components/binary/pump{ - dir = 8; - name = "Air to Pure" - }, /obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ + dir = 1 + }, +/obj/machinery/meter, /turf/open/floor/plasteel/cafeteria, /area/engine/atmos) "aTf" = ( -/obj/machinery/atmospherics/pipe/manifold/cyan/visible, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -23430,6 +23382,10 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 8; + name = "Air to Pure" + }, /turf/open/floor/plasteel/dark, /area/engine/atmos) "aTg" = ( @@ -23690,7 +23646,10 @@ /area/crew_quarters/bar/atrium) "aTH" = ( /obj/structure/table/wood, -/obj/item/reagent_containers/food/drinks/coffee, +/obj/item/reagent_containers/food/drinks/coffee{ + pixel_x = -4; + pixel_y = 2 + }, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -24567,7 +24526,6 @@ /turf/open/floor/plating, /area/security/prison) "aUL" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/machinery/light/small{ dir = 8 }, @@ -24581,12 +24539,15 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/turf/open/floor/plasteel/dark, -/area/engine/atmos) -"aUM" = ( /obj/machinery/atmospherics/pipe/simple/green/visible{ dir = 6 }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 9 + }, +/turf/open/floor/plasteel/dark, +/area/engine/atmos) +"aUM" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -24598,16 +24559,20 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) "aUN" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible, /obj/machinery/atmospherics/pipe/simple/green/visible{ dir = 4 }, /obj/effect/turf_decal/stripes/line{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/general/visible, /turf/open/floor/plasteel, /area/engine/atmos) "aUO" = ( @@ -24627,21 +24592,11 @@ /turf/open/floor/plasteel, /area/engine/atmos) "aUP" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible{ +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/layer_manifold{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/general/visible, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, +/turf/open/floor/plating, /area/engine/atmos) "aUQ" = ( /obj/machinery/atmospherics/pipe/simple/green/visible{ @@ -24651,6 +24606,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/effect/landmark/start/atmospheric_technician, /turf/open/floor/plasteel/dark/corner, /area/engine/atmos) "aUR" = ( @@ -24715,7 +24671,6 @@ /obj/structure/cable/white{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -24729,7 +24684,6 @@ /turf/open/floor/plasteel, /area/engine/atmos) "aUW" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible, /obj/machinery/atmospherics/pipe/simple/green/visible{ dir = 4 }, @@ -24746,12 +24700,13 @@ /obj/structure/window/reinforced{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 10 - }, /obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 4 + }, /turf/open/floor/plasteel/white/corner, /area/engine/atmos) "aUY" = ( @@ -25865,16 +25820,13 @@ /area/engine/atmos) "aWy" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 4 - }, -/turf/open/floor/plating, -/area/engine/atmos) -"aWz" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ +/obj/machinery/atmospherics/pipe/layer_manifold{ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/cyan/visible, +/turf/open/floor/plating, +/area/engine/atmos) +"aWz" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -25886,6 +25838,11 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 4; + name = "CO2 to Pure" + }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) "aWA" = ( @@ -25896,11 +25853,6 @@ dir = 1; pixel_y = 1 }, -/obj/machinery/atmospherics/pipe/simple/green/visible, -/obj/machinery/atmospherics/components/binary/pump{ - dir = 4; - name = "CO2 to Pure" - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -25911,73 +25863,19 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/engine/atmos) "aWB" = ( -/obj/machinery/atmospherics/pipe/manifold4w/yellow/visible, /obj/effect/turf_decal/stripes/line{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/general/visible, /turf/open/floor/plasteel, /area/engine/atmos) "aWC" = ( -/obj/machinery/atmospherics/components/unary/thermomachine/heater{ - dir = 8 - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/delivery, -/turf/open/floor/plasteel, -/area/engine/atmos) -"aWD" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 8 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"aWE" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 4 - }, -/obj/machinery/meter, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"aWF" = ( -/obj/machinery/light{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, /turf/open/floor/plasteel, /area/engine/atmos) "aWG" = ( @@ -26027,48 +25925,24 @@ /turf/open/floor/plasteel, /area/engine/atmos) "aWM" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/manifold/cyan/visible, +/turf/open/space, /area/engine/atmos) "aWN" = ( +/obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 6 }, -/obj/effect/landmark/event_spawn, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, +/turf/open/floor/plating, /area/engine/atmos) "aWO" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/yellow/visible, /obj/effect/turf_decal/stripes/line{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 6 + }, /turf/open/floor/plasteel, /area/engine/atmos) "aWP" = ( @@ -26076,7 +25950,6 @@ dir = 4 }, /obj/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/green/visible, /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 }, @@ -26086,6 +25959,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/open/floor/plasteel/white/corner, /area/engine/atmos) "aWR" = ( @@ -26853,7 +26727,6 @@ /turf/open/floor/engine/co2, /area/engine/atmos) "aXY" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -26865,6 +26738,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) "aXZ" = ( @@ -26874,7 +26748,6 @@ /obj/structure/window/reinforced{ dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/green/visible, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -26885,81 +26758,13 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) -"aYa" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"aYb" = ( -/obj/machinery/atmospherics/components/unary/thermomachine/heater/on{ - dir = 4 - }, -/obj/effect/turf_decal/delivery, -/turf/open/floor/plasteel, -/area/engine/atmos) -"aYc" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"aYd" = ( +"aYf" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"aYe" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"aYf" = ( -/obj/structure/table/reinforced, -/obj/item/folder/yellow, -/obj/item/lightreplacer, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, /turf/open/floor/plasteel, /area/engine/atmos) "aYg" = ( @@ -26997,27 +26802,23 @@ /turf/open/floor/plasteel, /area/engine/atmos) "aYj" = ( -/obj/structure/table/reinforced, -/obj/item/wrench, -/obj/item/tank/internals/emergency_oxygen/engi, -/obj/item/tank/internals/emergency_oxygen/engi, /obj/machinery/newscaster{ pixel_x = 32 }, /obj/effect/turf_decal/bot, +/obj/effect/turf_decal/stripes/end{ + dir = 1 + }, +/obj/machinery/suit_storage_unit/atmos, /turf/open/floor/plasteel, /area/engine/atmos) "aYk" = ( -/obj/structure/table/reinforced, -/obj/item/clothing/gloves/color/black, -/obj/item/clothing/suit/hazardvest, -/obj/item/clothing/mask/gas, -/obj/item/clothing/gloves/color/black, -/obj/item/clothing/suit/hazardvest, -/obj/item/clothing/mask/gas, /obj/effect/turf_decal/stripes/line{ dir = 8 }, +/obj/machinery/atmospherics/components/unary/thermomachine/heater{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "aYl" = ( @@ -27035,13 +26836,15 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 8 + }, /turf/open/floor/plasteel, /area/engine/atmos) "aYm" = ( /obj/structure/cable/white{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 8 }, @@ -27058,7 +26861,6 @@ /turf/open/floor/plasteel, /area/engine/atmos) "aYn" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -27072,20 +26874,13 @@ /turf/open/floor/plasteel, /area/engine/atmos) "aYo" = ( -/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ - dir = 8 - }, /obj/effect/turf_decal/stripes/line{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plasteel, /area/engine/atmos) "aYp" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible, -/obj/machinery/atmospherics/components/binary/pump{ - dir = 8; - name = "O2 to Pure" - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -27096,12 +26891,12 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ + dir = 8 + }, /turf/open/floor/plasteel/dark, /area/engine/atmos) "aYq" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 10 - }, /obj/effect/decal/cleanable/dirt, /obj/structure/sign/warning/securearea{ pixel_x = 32 @@ -27124,6 +26919,11 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 8; + name = "O2 to Pure" + }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) "aYr" = ( @@ -28136,10 +27936,6 @@ /turf/open/floor/plating, /area/engine/atmos) "aZT" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -28150,6 +27946,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/components/trinary/filter/atmos/co2, /turf/open/floor/plasteel/dark, /area/engine/atmos) "aZU" = ( @@ -28157,7 +27954,6 @@ dir = 8 }, /obj/structure/window/reinforced, -/obj/machinery/atmospherics/components/trinary/filter/atmos/co2, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -28168,75 +27964,10 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, +/obj/structure/reagent_dispensers/watertank/high, /turf/open/floor/plasteel/dark, /area/engine/atmos) -"aZV" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 4 - }, -/obj/machinery/portable_atmospherics/canister, -/obj/effect/turf_decal/bot, -/turf/open/floor/plasteel, -/area/engine/atmos) -"aZW" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"aZX" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"aZY" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 8 - }, -/obj/machinery/meter, -/obj/item/wrench, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"aZZ" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 8 - }, -/obj/machinery/portable_atmospherics/canister, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "baa" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 @@ -28270,8 +28001,8 @@ "bac" = ( /obj/structure/closet/secure_closet/atmospherics, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/stripes/end{ - dir = 1 +/obj/effect/turf_decal/stripes/line{ + dir = 8 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -28300,23 +28031,6 @@ /obj/structure/cable/white{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bag" = ( -/obj/machinery/atmospherics/components/trinary/mixer/airmix{ - dir = 1 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -28337,11 +28051,6 @@ dir = 1; pixel_y = 1 }, -/obj/machinery/atmospherics/pipe/simple/green/visible, -/obj/machinery/atmospherics/components/binary/pump/on{ - dir = 8; - name = "O2 to Airmix" - }, /obj/effect/turf_decal/tile/blue{ dir = 1 }, @@ -28349,10 +28058,13 @@ /obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bai" = ( -/obj/machinery/atmospherics/pipe/manifold/yellow/visible, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -28363,6 +28075,11 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/components/binary/pump/on{ + dir = 8; + name = "O2 to Airmix" + }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) "baj" = ( @@ -29016,7 +28733,6 @@ /turf/open/space, /area/space/nearstation) "bbA" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/structure/sign/warning/securearea{ pixel_x = -32 }, @@ -29038,10 +28754,10 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) "bbB" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -29052,58 +28768,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) -"bbC" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 4 - }, -/obj/machinery/meter, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bbD" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/start/atmospheric_technician, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bbE" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/components/trinary/filter{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "bbF" = ( /obj/structure/disposalpipe/segment{ dir = 5 @@ -29157,7 +28824,6 @@ /obj/structure/cable/white{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/effect/landmark/start/atmospheric_technician, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -29171,13 +28837,6 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) -"bbK" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "bbL" = ( /obj/machinery/computer/atmos_control/tank/oxygen_tank{ dir = 8 @@ -29185,11 +28844,11 @@ /obj/structure/window/reinforced{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/green/visible, /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bbM" = ( @@ -29205,6 +28864,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) "bbN" = ( @@ -29870,10 +29530,6 @@ /turf/open/floor/engine/plasma, /area/engine/atmos) "bda" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -29884,6 +29540,11 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 4; + name = "Plasma to Pure" + }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) "bdb" = ( @@ -29894,11 +29555,6 @@ dir = 1; pixel_y = 1 }, -/obj/machinery/atmospherics/pipe/simple/green/visible, -/obj/machinery/atmospherics/components/binary/pump{ - dir = 4; - name = "Plasma to Pure" - }, /obj/effect/turf_decal/tile/purple{ dir = 1 }, @@ -29908,55 +29564,17 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, +/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bdc" = ( -/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ - dir = 4 - }, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line{ dir = 8 }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bdd" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 4 - }, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/portable_atmospherics/canister, -/obj/effect/turf_decal/bot, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bde" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bdf" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 8 - }, -/obj/machinery/meter, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, +/obj/machinery/atmospherics/pipe/simple/general/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bdg" = ( @@ -30000,9 +29618,6 @@ dir = 4 }, /obj/structure/window/reinforced, -/obj/machinery/atmospherics/components/trinary/filter/atmos/o2{ - dir = 1 - }, /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ dir = 4 @@ -30010,12 +29625,10 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bdl" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 4 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -30026,6 +29639,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/components/trinary/filter/atmos/o2{ + dir = 1 + }, /turf/open/floor/plasteel/dark, /area/engine/atmos) "bdm" = ( @@ -30711,7 +30327,6 @@ /obj/structure/window/reinforced{ dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/green/visible, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/purple{ dir = 1 @@ -30719,6 +30334,7 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bey" = ( @@ -30735,28 +30351,9 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) -"bez" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "beA" = ( -/obj/structure/table/reinforced, -/obj/item/analyzer{ - pixel_x = 7; - pixel_y = 3 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -30767,10 +30364,12 @@ dir = 4; pixel_x = -24 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/dark/corner{ dir = 1 }, @@ -30795,17 +30394,16 @@ /turf/closed/wall, /area/engine/atmos) "beF" = ( -/obj/structure/table/reinforced, -/obj/item/stack/packageWrap, -/obj/item/hand_labeler, /obj/effect/turf_decal/stripes/line{ dir = 8 }, +/obj/machinery/atmospherics/components/unary/thermomachine/freezer{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "beG" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -30818,21 +30416,7 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) -"beH" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 5 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "beI" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible, -/obj/machinery/atmospherics/components/binary/pump{ - dir = 8; - name = "N2 to Pure" - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -30843,6 +30427,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 5 + }, /turf/open/floor/plasteel/dark, /area/engine/atmos) "beJ" = ( @@ -30852,12 +30439,6 @@ /obj/machinery/light/small{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 10 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -30865,6 +30446,14 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 8; + name = "N2 to Pure" + }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) "beK" = ( @@ -31526,10 +31115,6 @@ /turf/open/floor/engine/plasma, /area/engine/atmos) "bfU" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -31541,6 +31126,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/components/trinary/filter/atmos/plasma, /turf/open/floor/plasteel/dark, /area/engine/atmos) "bfV" = ( @@ -31548,7 +31134,6 @@ dir = 8 }, /obj/structure/window/reinforced, -/obj/machinery/atmospherics/components/trinary/filter/atmos/plasma, /obj/effect/turf_decal/tile/purple{ dir = 1 }, @@ -31556,23 +31141,8 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bfW" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1; - name = "Port Mix to Port Ports" - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, +/obj/structure/closet/crate, /turf/open/floor/plasteel, /area/engine/atmos) "bfX" = ( @@ -31590,26 +31160,6 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) -"bfY" = ( -/obj/machinery/light{ - dir = 4 - }, -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1; - name = "Port Mix to Starboard Ports" - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "bfZ" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -31630,29 +31180,13 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) -"bgb" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 5 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "bgc" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 - }, /obj/effect/turf_decal/stripes/line{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 5 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bgd" = ( @@ -31663,11 +31197,6 @@ dir = 1; pixel_y = 1 }, -/obj/machinery/atmospherics/pipe/simple/green/visible, -/obj/machinery/atmospherics/components/binary/pump/on{ - dir = 8; - name = "N2 to Airmix" - }, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -31675,11 +31204,13 @@ /obj/effect/turf_decal/tile/red{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bge" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/manifold/yellow/visible, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -31690,6 +31221,11 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/components/binary/pump/on{ + dir = 8; + name = "N2 to Airmix" + }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) "bgf" = ( @@ -32184,7 +31720,6 @@ /turf/open/floor/plating, /area/security/main) "bhf" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/effect/decal/cleanable/dirt, /obj/structure/sign/warning/securearea{ pixel_x = -32 @@ -32202,50 +31737,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) -"bhg" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 1 - }, -/obj/machinery/meter, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bhh" = ( -/obj/machinery/atmospherics/pipe/manifold4w/general/visible, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bhi" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 10 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/turf/open/floor/plasteel/dark/corner{ - dir = 1 - }, -/area/engine/atmos) "bhj" = ( /obj/machinery/power/apc/highcap/five_k{ areastring = "/area/engine/atmos"; @@ -32347,7 +31841,6 @@ /obj/structure/cable/white{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, @@ -32395,27 +31888,12 @@ /obj/structure/window/reinforced{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/green/visible, /obj/effect/turf_decal/tile/red, /obj/effect/turf_decal/tile/red{ dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) -"bhu" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/engine/atmos) "bhv" = ( /obj/machinery/air_sensor/atmos/nitrogen_tank, /turf/open/floor/engine/n2, @@ -33356,34 +32834,29 @@ dir = 1; pixel_y = 1 }, -/obj/machinery/atmospherics/pipe/simple/green/visible, -/obj/machinery/atmospherics/components/binary/pump{ - dir = 4; - name = "N2O to Pure" - }, /obj/effect/turf_decal/tile/red{ dir = 4 }, /obj/effect/turf_decal/tile/red{ dir = 8 }, +/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ + dir = 4 + }, /turf/open/floor/plasteel/white/corner{ dir = 1 }, /area/engine/atmos) "biX" = ( -/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ - dir = 4 - }, /obj/effect/turf_decal/stripes/line{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/general/visible{ + dir = 5 + }, /turf/open/floor/plasteel, /area/engine/atmos) "biY" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 5 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -33394,75 +32867,12 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/general/visible{ + dir = 10 + }, /turf/open/floor/plasteel, /area/engine/atmos) "biZ" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1; - name = "Pure to Ports" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bja" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1; - name = "Mix to Ports" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bjb" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1; - name = "Air to Ports" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bjc" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/machinery/atmospherics/components/binary/pump{ - name = "Port Mix to Engine" - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -33473,15 +32883,14 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/components/unary/portables_connector/visible, +/obj/machinery/portable_atmospherics/canister, /turf/open/floor/plasteel, /area/engine/atmos) "bjd" = ( /obj/structure/cable/white{ icon_state = "1-4" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -33498,7 +32907,6 @@ /obj/structure/cable/white{ icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -33509,6 +32917,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 5 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bjf" = ( @@ -33596,8 +33007,6 @@ /obj/structure/cable/white{ icon_state = "1-8" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, -/obj/machinery/meter, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -33636,9 +33045,6 @@ dir = 4 }, /obj/structure/window/reinforced, -/obj/machinery/atmospherics/components/trinary/filter/atmos/n2{ - dir = 1 - }, /obj/effect/turf_decal/tile/red, /obj/effect/turf_decal/tile/red{ dir = 4 @@ -34546,42 +33952,49 @@ /obj/structure/window/reinforced{ dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/green/visible, /obj/effect/turf_decal/tile/red{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 5 + }, /turf/open/floor/plasteel/white/corner{ dir = 1 }, /area/engine/atmos) "bkK" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line{ dir = 10 }, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 4; + name = "Pure to Port" + }, /turf/open/floor/plasteel, /area/engine/atmos) "bkL" = ( /obj/effect/turf_decal/stripes/line, +/obj/machinery/atmospherics/pipe/manifold4w/general/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bkM" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible, -/obj/machinery/meter, /obj/effect/turf_decal/stripes/line, +/obj/machinery/atmospherics/pipe/manifold4w/general/visible, +/obj/machinery/meter, /turf/open/floor/plasteel, /area/engine/atmos) "bkN" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible, -/obj/machinery/meter, /obj/effect/turf_decal/stripes/line, +/obj/machinery/atmospherics/pipe/manifold/general/visible{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bkO" = ( /obj/effect/turf_decal/stripes/line, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 5 +/obj/machinery/atmospherics/pipe/simple/general/visible{ + dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -34592,13 +34005,6 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) -"bkQ" = ( -/obj/effect/turf_decal/stripes/line, -/obj/machinery/atmospherics/components/trinary/filter{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "bkR" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/corner{ @@ -34640,12 +34046,20 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bkU" = ( -/obj/effect/turf_decal/stripes/line, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/turf/open/floor/plasteel, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 10 + }, +/turf/open/floor/plasteel/dark, /area/engine/atmos) "bkV" = ( /obj/effect/decal/cleanable/dirt, @@ -34667,11 +34081,6 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bkX" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, -/obj/machinery/atmospherics/components/binary/valve{ - dir = 4; - name = "SM Coolant Loop" - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -34682,6 +34091,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/engine/atmos) "bkY" = ( @@ -34691,9 +34103,6 @@ /obj/machinery/light/small{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 10 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -34704,10 +34113,17 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) "bkZ" = ( /obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 10 + }, /turf/open/space, /area/engine/atmos) "bla" = ( @@ -35683,91 +35099,103 @@ dir = 8 }, /obj/structure/window/reinforced, -/obj/machinery/atmospherics/components/trinary/filter/atmos/n2o, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/red{ dir = 8 }, +/obj/machinery/portable_atmospherics/canister/nitrogen, /turf/open/floor/plasteel/cafeteria, /area/engine/atmos) "bmK" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 5 - }, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/engine/atmos) "bmL" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ - dir = 1 - }, /obj/effect/turf_decal/bot, +/obj/machinery/atmospherics/components/binary/pump{ + name = "Port to Mix" + }, /turf/open/floor/plasteel, /area/engine/atmos) "bmM" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 9 - }, /obj/effect/turf_decal/bot, +/obj/machinery/portable_atmospherics/canister, +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bmN" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible, /obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/components/binary/pump{ + name = "Mix to Port" + }, /turf/open/floor/plasteel, /area/engine/atmos) "bmO" = ( /obj/effect/turf_decal/bot, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, +/obj/machinery/atmospherics/pipe/simple/general/visible{ + dir = 5 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bmP" = ( /obj/effect/turf_decal/bot, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 4; + name = "Port to Waste" + }, /turf/open/floor/plasteel, /area/engine/atmos) "bmQ" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 6 - }, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ + dir = 1 + }, /turf/open/floor/plasteel/dark/corner{ dir = 1 }, /area/engine/atmos) "bmR" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 1; + name = "Air to Ports" + }, /turf/open/floor/plasteel/dark/corner{ dir = 1 }, /area/engine/atmos) "bmS" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ - dir = 1 - }, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ + dir = 1 + }, /turf/open/floor/plasteel/dark/corner{ dir = 1 }, /area/engine/atmos) "bmT" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ - dir = 1 - }, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 4 + }, /turf/open/floor/plasteel/checker, /area/engine/atmos) "bmU" = ( @@ -35814,7 +35242,9 @@ /obj/item/stack/sheet/glass/fifty, /obj/item/stack/rods/fifty, /obj/effect/turf_decal/bot, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bmY" = ( @@ -35850,9 +35280,6 @@ dir = 8 }, /obj/item/twohanded/required/kirbyplants/random, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 9 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -35863,11 +35290,30 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/engine/atmos) "bnb" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 5 +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 9 + }, +/turf/open/floor/plasteel/dark, +/area/engine/atmos) +"bnc" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 4 }, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -35879,15 +35325,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) -"bnc" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 4 - }, -/turf/open/floor/plating, -/area/engine/atmos) "bnd" = ( /obj/structure/lattice/catwalk, /obj/machinery/atmospherics/pipe/simple/orange/visible{ @@ -36579,28 +36019,15 @@ /area/space/nearstation) "bok" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ - dir = 8 - }, -/obj/machinery/status_display/evac{ - pixel_x = -32 +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plating, /area/engine/atmos) "bol" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/green/visible, -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 - }, -/turf/open/floor/plating, -/area/engine/atmos) -"bom" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/yellow/visible, -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 - }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plating, /area/engine/atmos) "bon" = ( @@ -36620,9 +36047,10 @@ /turf/open/floor/plasteel, /area/engine/atmos) "boo" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/manifold/cyan/visible, -/turf/open/floor/plating, +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 4 + }, +/turf/closed/wall/r_wall, /area/engine/atmos) "bop" = ( /obj/structure/table/reinforced, @@ -36636,9 +36064,6 @@ /turf/open/floor/plasteel, /area/engine/atmos) "boq" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 10 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -36649,6 +36074,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bor" = ( @@ -36670,7 +36098,6 @@ /obj/item/clipboard, /obj/effect/decal/cleanable/dirt, /obj/item/toy/figure/atmos, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/engine/atmos) @@ -37595,7 +37022,6 @@ /obj/machinery/atmospherics/pipe/simple/green/visible{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/effect/turf_decal/tile/green{ dir = 1 }, @@ -37605,10 +37031,10 @@ /obj/effect/turf_decal/tile/green{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bpR" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible, /obj/machinery/atmospherics/components/binary/pump/on{ dir = 8; name = "Unfiltered & Air to Mix" @@ -37633,13 +37059,11 @@ }, /area/engine/atmos) "bpT" = ( -/obj/machinery/atmospherics/components/binary/pump{ - name = "Pure to Mix" - }, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel/dark/corner{ dir = 1 }, @@ -37662,6 +37086,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/meter, /turf/open/floor/plasteel/dark/corner{ dir = 1 }, @@ -37734,7 +37159,6 @@ /obj/item/clothing/head/welding, /obj/structure/table/reinforced, /obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/effect/turf_decal/bot, /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 @@ -38947,22 +38371,27 @@ /obj/machinery/computer/atmos_control/tank/mix_tank{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/effect/turf_decal/tile/green{ dir = 1 }, /obj/effect/turf_decal/tile/green{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 5 + }, /turf/open/floor/plasteel, /area/engine/atmos) "brW" = ( -/obj/machinery/atmospherics/pipe/manifold/green/visible{ - dir = 8 - }, /obj/effect/turf_decal/stripes/line{ dir = 9 }, +/obj/machinery/atmospherics/pipe/manifold/green/visible{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "brX" = ( @@ -39017,17 +38446,11 @@ /obj/item/wrench, /obj/item/clothing/mask/gas, /obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 6 - }, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/engine/atmos) "bsd" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ - dir = 4 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -39038,13 +38461,13 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bse" = ( /obj/structure/table/reinforced, /obj/item/storage/belt/utility, /obj/item/t_scanner, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/engine/atmos) @@ -40226,13 +39649,14 @@ dir = 4; pixel_x = -22 }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/effect/turf_decal/bot, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 6 + }, /turf/open/floor/plasteel, /area/engine/atmos) "btU" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -40243,11 +39667,16 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ + dir = 8 + }, /turf/open/floor/plasteel, /area/engine/atmos) "btV" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/effect/turf_decal/bot, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 10 + }, /turf/open/floor/plasteel, /area/engine/atmos) "btW" = ( @@ -40326,47 +39755,53 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bub" = ( /obj/structure/cable/white{ icon_state = "4-8" }, -/obj/machinery/portable_atmospherics/canister/nitrous_oxide, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "buc" = ( /obj/structure/cable/white{ icon_state = "2-8" }, -/obj/machinery/portable_atmospherics/canister/nitrogen, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bud" = ( -/obj/machinery/portable_atmospherics/canister/oxygen, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 10 }, -/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bue" = ( -/obj/machinery/portable_atmospherics/canister/air, /obj/machinery/camera{ c_tag = "Atmospherics - Desk"; dir = 8; name = "atmospherics camera" }, -/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "buf" = ( @@ -41024,9 +40459,6 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, /turf/open/floor/plasteel, /area/engine/atmos) "bvn" = ( @@ -41036,9 +40468,6 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, /turf/open/floor/plasteel, /area/engine/atmos) "bvo" = ( @@ -41049,9 +40478,6 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, /turf/open/floor/plasteel, /area/engine/atmos) "bvp" = ( @@ -41059,9 +40485,6 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, /turf/open/floor/plasteel, /area/engine/atmos) "bvq" = ( @@ -43155,7 +42578,9 @@ /obj/structure/cable/white{ icon_state = "0-2" }, -/obj/effect/spawner/structure/window/reinforced/tinted, +/obj/effect/spawner/structure/window/reinforced/tinted/electrochromatic{ + electrochromatic_id = "!interrogation_room" + }, /turf/open/floor/plating, /area/security/main) "byP" = ( @@ -44229,7 +43654,9 @@ /obj/structure/cable/white{ icon_state = "0-4" }, -/obj/effect/spawner/structure/window/reinforced/tinted, +/obj/effect/spawner/structure/window/reinforced/tinted/electrochromatic{ + electrochromatic_id = "!interrogation_room" + }, /turf/open/floor/plating, /area/security/main) "bAt" = ( @@ -45536,10 +44963,12 @@ /area/security/main) "bCm" = ( /obj/structure/cable/white, -/obj/effect/spawner/structure/window/reinforced/tinted, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, +/obj/effect/spawner/structure/window/reinforced/tinted/electrochromatic{ + electrochromatic_id = "!interrogation_room" + }, /turf/open/floor/plating, /area/security/main) "bCn" = ( @@ -45559,6 +44988,10 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/button/electrochromatic{ + id = "!interrogation_room"; + pixel_y = -26 + }, /turf/open/floor/plasteel/dark, /area/security/main) "bCo" = ( @@ -61243,10 +60676,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/machinery/airalarm{ - dir = 1; - pixel_y = -22 - }, /obj/machinery/door/firedoor, /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -61261,10 +60690,6 @@ dir = 4 }, /obj/machinery/light, -/obj/machinery/firealarm{ - dir = 1; - pixel_y = -26 - }, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, @@ -63314,43 +62739,36 @@ /turf/open/floor/plasteel/dark, /area/library) "cct" = ( -/obj/structure/table/wood, -/obj/item/flashlight/lamp, -/obj/machinery/computer/security/telescreen/entertainment{ - pixel_x = -32 +/obj/structure/table/wood/fancy, +/obj/machinery/door/window{ + name = "Secure Art Exhibition" }, -/obj/item/radio/intercom{ - name = "Station Intercom"; - pixel_y = 26 - }, -/turf/open/floor/plasteel/dark, -/area/library) -"ccu" = ( -/obj/machinery/light/small{ - dir = 1 - }, -/obj/structure/table/wood, -/obj/item/folder, -/obj/item/pen, -/obj/machinery/newscaster{ +/obj/structure/sign/painting/library_secure{ pixel_y = 32 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ +/turf/open/floor/carpet, +/area/library) +"ccu" = ( +/obj/structure/table/wood/fancy, +/obj/structure/window/reinforced{ dir = 4 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 +/obj/structure/window/reinforced, +/obj/structure/sign/painting/library_secure{ + pixel_y = 32 }, -/turf/open/floor/plasteel/dark, +/turf/open/floor/carpet, /area/library) "ccv" = ( -/obj/machinery/computer/libraryconsole, -/obj/structure/table/wood, -/turf/open/floor/plasteel/dark, +/obj/structure/extinguisher_cabinet{ + pixel_y = 32 + }, +/obj/machinery/camera{ + c_tag = "Library - Aft"; + dir = 2; + name = "library camera" + }, +/turf/open/floor/wood, /area/library) "ccw" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ @@ -64492,7 +63910,7 @@ /obj/structure/chair/office/dark{ dir = 8 }, -/obj/effect/landmark/start/librarian, +/obj/effect/landmark/start/assistant, /turf/open/floor/plasteel/dark, /area/library) "ceg" = ( @@ -64505,71 +63923,21 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 8 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/library) -"cei" = ( -/obj/structure/chair/comfy/black{ - dir = 8 - }, -/obj/machinery/newscaster{ - pixel_x = 32 - }, -/obj/machinery/camera{ - c_tag = "Library - Fore"; - dir = 8; - name = "library camera" - }, -/turf/open/floor/plasteel/dark, +/turf/open/floor/plasteel/grimy, /area/library) "cej" = ( -/obj/machinery/photocopier, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/library) -"cek" = ( -/obj/structure/chair/office/dark{ - dir = 1 - }, -/obj/machinery/atmospherics/components/unary/vent_pump/on, -/turf/open/floor/plasteel/dark, +/obj/effect/landmark/start/librarian, +/turf/open/floor/plasteel/grimy, /area/library) "cel" = ( -/obj/structure/table/wood, -/obj/item/paper_bin, -/obj/item/pen, -/obj/machinery/status_display/evac{ - pixel_x = 32 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ +/obj/structure/chair/sofa/right{ + icon_state = "sofaend_right"; dir = 8 }, -/turf/open/floor/plasteel/dark, +/obj/structure/sign/painting/library{ + pixel_x = 32 + }, +/turf/open/floor/wood, /area/library) "cem" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ @@ -65746,34 +65114,16 @@ }, /turf/open/floor/plasteel/grimy, /area/library) -"cfY" = ( -/obj/item/twohanded/required/kirbyplants/random, -/obj/machinery/light/small{ - dir = 4 +"cfZ" = ( +/obj/item/radio/intercom{ + name = "Station Intercom"; + pixel_x = -26 + }, +/obj/structure/sign/painting/library{ + pixel_y = -32 }, /turf/open/floor/wood, /area/library) -"cfZ" = ( -/obj/structure/sign/warning/nosmoking, -/turf/closed/wall, -/area/library) -"cga" = ( -/obj/machinery/door/morgue{ - name = "Private Study" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/library) "cgb" = ( /obj/structure/sign/plaques/kiddie/library{ pixel_x = -32 @@ -66921,61 +66271,28 @@ /obj/item/twohanded/required/kirbyplants/random, /turf/open/floor/wood, /area/library) -"chQ" = ( -/obj/machinery/bookbinder, -/turf/open/floor/wood, -/area/library) -"chR" = ( -/obj/machinery/light{ - dir = 1 - }, -/obj/machinery/newscaster{ - pixel_y = 32 - }, -/obj/structure/bookcase/random, -/turf/open/floor/wood, -/area/library) -"chS" = ( -/obj/structure/chair/comfy/brown, -/obj/effect/landmark/start/assistant, -/turf/open/floor/wood, -/area/library) -"chT" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/wood, -/area/library) -"chU" = ( -/obj/machinery/photocopier, -/obj/structure/extinguisher_cabinet{ - pixel_y = 32 - }, -/turf/open/floor/wood, -/area/library) "chV" = ( -/obj/machinery/light{ - dir = 1 - }, /obj/machinery/newscaster{ - pixel_y = 32 + pixel_x = -32 }, -/obj/structure/bookcase/manuals/research_and_development, -/obj/machinery/camera{ - c_tag = "Library"; - name = "library camera" - }, -/turf/open/floor/wood, +/turf/open/floor/plasteel/dark, /area/library) "chW" = ( -/obj/structure/chair/comfy/brown, -/obj/item/radio/intercom{ - name = "Station Intercom"; - pixel_y = 26 - }, -/turf/open/floor/wood, +/obj/machinery/holopad, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel/grimy, /area/library) "chX" = ( -/obj/machinery/vending/coffee, -/turf/open/floor/wood, +/obj/structure/table/wood, +/obj/item/newspaper{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/reagent_containers/food/drinks/coffee{ + pixel_x = -4; + pixel_y = 2 + }, +/turf/open/floor/plasteel/dark, /area/library) "chY" = ( /obj/machinery/door/poddoor/shutters/preopen{ @@ -67864,10 +67181,6 @@ }, /turf/open/floor/plasteel/grimy, /area/library) -"cju" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/turf/open/floor/plasteel/grimy, -/area/library) "cjv" = ( /obj/machinery/door/airlock/public/glass{ name = "Library Access" @@ -69490,10 +68803,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/wood, /area/library) -"cmv" = ( -/obj/machinery/holopad, -/turf/open/floor/wood, -/area/library) "cmw" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/extinguisher_cabinet{ @@ -70370,7 +69679,7 @@ /turf/open/floor/wood, /area/library) "cnP" = ( -/obj/structure/bookcase/manuals/medical, +/obj/structure/bookcase/random, /turf/open/floor/wood, /area/library) "cnQ" = ( @@ -75138,8 +74447,6 @@ /area/library) "cwr" = ( /obj/structure/easel, -/obj/item/canvas/twentythreeXnineteen, -/obj/item/canvas/twentythreeXtwentythree, /obj/item/canvas/twentythreeXtwentythree, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -77653,7 +76960,6 @@ name = "Maintenance Hatch"; req_access_txt = "12" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ @@ -79071,7 +78377,10 @@ pixel_x = 3; pixel_y = 3 }, -/obj/item/newspaper, +/obj/item/newspaper{ + pixel_x = 3; + pixel_y = 3 + }, /obj/machinery/status_display/evac{ pixel_x = -32 }, @@ -80784,7 +80093,10 @@ pixel_x = 7; pixel_y = 11 }, -/obj/item/newspaper, +/obj/item/newspaper{ + pixel_x = 3; + pixel_y = 3 + }, /obj/item/pen/red, /turf/open/floor/wood{ icon_state = "wood-broken2" @@ -81511,7 +80823,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/locker) "cGO" = ( -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -82774,18 +82086,12 @@ /turf/open/floor/plasteel, /area/crew_quarters/dorms) "cJl" = ( -/obj/structure/cable/white{ - icon_state = "4-8" +/obj/structure/lattice, +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 10 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/crew_quarters/dorms) +/turf/open/space, +/area/engine/atmos) "cJm" = ( /obj/structure/cable/white{ icon_state = "4-8" @@ -84099,9 +83405,6 @@ /turf/open/floor/plasteel, /area/crew_quarters/dorms) "cLa" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 4 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -84112,6 +83415,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 10 + }, /turf/open/floor/plasteel, /area/crew_quarters/dorms) "cLb" = ( @@ -98542,17 +97848,17 @@ /obj/structure/sign/poster/official/science{ pixel_x = -32 }, +/obj/item/clothing/mask/gas, /turf/open/floor/plasteel, /area/science/explab) "djC" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible, /obj/effect/turf_decal/stripes/line{ dir = 10 }, +/obj/machinery/rnd/bepis, /turf/open/floor/plasteel, /area/science/explab) "djD" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible, /obj/machinery/light{ dir = 1 }, @@ -98563,7 +97869,6 @@ /turf/open/floor/plasteel, /area/science/explab) "djE" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible, /obj/effect/turf_decal/stripes/line{ dir = 6 }, @@ -99547,34 +98852,20 @@ /obj/machinery/newscaster{ pixel_x = -32 }, -/obj/item/crowbar, -/obj/item/wrench, -/obj/item/clothing/mask/gas, /obj/effect/turf_decal/bot, +/obj/item/storage/bag/money, /turf/open/floor/plasteel, /area/science/explab) "dlp" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 5 - }, /obj/effect/turf_decal/tile/purple{ dir = 1 }, +/obj/structure/chair/office/light{ + dir = 8 + }, /turf/open/floor/plasteel/white, /area/science/explab) "dlq" = ( -/obj/machinery/atmospherics/components/trinary/filter{ - dir = 8 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 1 - }, -/turf/open/floor/plasteel/white, -/area/science/explab) -"dlr" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 9 - }, /obj/effect/turf_decal/tile/purple{ dir = 1 }, @@ -108635,7 +107926,7 @@ /obj/structure/sign/poster/contraband/random{ pixel_y = -32 }, -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/open/floor/plating, /area/crew_quarters/abandoned_gambling_den) "dBS" = ( @@ -110687,7 +109978,10 @@ pixel_x = 3; pixel_y = 3 }, -/obj/item/newspaper, +/obj/item/newspaper{ + pixel_x = 3; + pixel_y = 3 + }, /turf/open/floor/plating, /area/security/detectives_office/private_investigators_office) "dFu" = ( @@ -111550,7 +110844,10 @@ /area/crew_quarters/theatre/abandoned) "dGH" = ( /obj/structure/table/wood, -/obj/item/newspaper, +/obj/item/newspaper{ + pixel_x = 3; + pixel_y = 3 + }, /obj/item/clothing/head/bowler, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -125764,6 +125061,14 @@ }, /turf/open/floor/plasteel/dark, /area/library) +"emA" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible, +/turf/open/floor/plating, +/area/engine/atmos) "exE" = ( /obj/machinery/air_sensor/atmos/toxins_mixing_tank, /turf/open/floor/engine/vacuum, @@ -125805,7 +125110,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/machinery/chem_dispenser, +/obj/machinery/chem_dispenser/apothecary, /turf/open/floor/plasteel/dark, /area/medical/medbay/central) "eMD" = ( @@ -125838,6 +125143,24 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/maintenance/port/fore) +"eRX" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 4; + name = "N2O to Pure" + }, +/obj/machinery/atmospherics/pipe/simple/green/visible, +/turf/open/floor/plasteel/dark, +/area/engine/atmos) "eTv" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -126040,6 +125363,17 @@ /obj/structure/closet/crate/coffin, /turf/open/floor/plating, /area/chapel/office) +"gjg" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/airalarm{ + dir = 1; + pixel_y = -22 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port) "gmj" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall/r_wall, @@ -126108,6 +125442,12 @@ }, /turf/open/floor/plasteel/dark, /area/science/mixing) +"gOM" = ( +/obj/structure/sign/painting/library{ + pixel_y = -32 + }, +/turf/open/floor/wood, +/area/library) "gPv" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -126204,6 +125544,12 @@ }, /turf/open/floor/plasteel, /area/security/prison) +"hwV" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/closed/wall, +/area/engine/atmos) "hFo" = ( /obj/structure/lattice, /obj/structure/disposalpipe/segment{ @@ -126355,6 +125701,12 @@ }, /turf/open/floor/plasteel/dark, /area/science/mixing) +"jaZ" = ( +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 4 + }, +/turf/closed/wall/r_wall, +/area/engine/atmos) "jdO" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -126395,6 +125747,12 @@ /obj/item/integrated_circuit_printer, /turf/open/floor/plasteel/white/side, /area/science/circuit) +"jqs" = ( +/obj/structure/sign/painting/library{ + pixel_y = 32 + }, +/turf/open/floor/wood, +/area/library) "jqM" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line{ @@ -126513,6 +125871,17 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plating, /area/science/mixing) +"jVB" = ( +/obj/structure/table/wood/fancy, +/obj/structure/window/reinforced{ + dir = 8 + }, +/obj/structure/window/reinforced, +/obj/structure/sign/painting/library_secure{ + pixel_y = 32 + }, +/turf/open/floor/carpet, +/area/library) "kam" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/conveyor{ @@ -126616,11 +125985,26 @@ }, /turf/open/floor/plasteel/white, /area/science/mixing) +"kQS" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 1; + name = "Port to Turbine" + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "lak" = ( /turf/open/floor/plasteel/white/side{ dir = 10 }, /area/science/circuit) +"lhL" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/manifold/yellow/visible, +/turf/open/space, +/area/engine/atmos) "loI" = ( /obj/machinery/autolathe, /obj/machinery/door/window/southleft{ @@ -126638,6 +126022,20 @@ }, /turf/open/floor/plasteel/white, /area/science/lab) +"lqA" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/atmospherics/components/trinary/filter/atmos/n2o, +/turf/open/floor/plasteel/dark, +/area/engine/atmos) "lti" = ( /obj/machinery/atmospherics/components/trinary/mixer/flipped, /obj/effect/turf_decal/tile/neutral{ @@ -126854,6 +126252,16 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/circuit/green, /area/science/research/abandoned) +"mxy" = ( +/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ + dir = 8 + }, +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/engine/atmos) "mIi" = ( /obj/item/electropack/shockcollar, /obj/item/assembly/signaler, @@ -126886,6 +126294,12 @@ }, /turf/open/floor/plasteel/white, /area/science/research) +"mRS" = ( +/obj/machinery/light{ + dir = 1 + }, +/turf/open/floor/wood, +/area/library) "mWZ" = ( /obj/machinery/atmospherics/components/binary/pump, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -126925,6 +126339,17 @@ /obj/machinery/atmospherics/pipe/simple/general/hidden, /turf/closed/wall/r_wall, /area/maintenance/disposal/incinerator) +"oek" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/camera{ + c_tag = "Library - Aft"; + dir = 2; + name = "library camera" + }, +/turf/open/floor/plasteel/grimy, +/area/library) "oHk" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -127023,6 +126448,14 @@ }, /turf/open/floor/plasteel/white, /area/science/research) +"oVn" = ( +/obj/effect/turf_decal/stripes/line, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 4; + name = "Ports to Engine" + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "oYI" = ( /obj/machinery/igniter/incinerator_toxmix, /turf/open/floor/engine/vacuum, @@ -127132,6 +126565,10 @@ }, /turf/open/floor/plating, /area/science/research/abandoned) +"pLF" = ( +/obj/machinery/light, +/turf/open/floor/wood, +/area/library) "pQm" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable/white{ @@ -127149,6 +126586,22 @@ }, /turf/open/floor/plasteel, /area/science/research/abandoned) +"qej" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/atmospherics/components/trinary/filter/atmos/n2{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/engine/atmos) "qeN" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden, /obj/effect/turf_decal/tile/neutral{ @@ -127317,6 +126770,15 @@ "saw" = ( /turf/closed/wall, /area/science/circuit) +"sby" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/atmospherics/components/trinary/mixer/airmix{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "sfo" = ( /obj/effect/decal/remains/xeno, /turf/open/floor/engine/vacuum, @@ -127396,6 +126858,15 @@ "tCh" = ( /turf/closed/wall, /area/science/misc_lab) +"tDx" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/light{ + dir = 1 + }, +/turf/open/floor/plasteel/grimy, +/area/library) "tMk" = ( /turf/open/floor/plasteel/white/side{ dir = 10 @@ -127545,6 +127016,23 @@ /obj/effect/landmark/start/paramedic, /turf/open/floor/plasteel/white, /area/medical/storage) +"vFd" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 5 + }, +/turf/open/floor/plating, +/area/engine/atmos) +"vLX" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 8 + }, +/obj/structure/sign/plaques/kiddie/library{ + pixel_x = 32; + pixel_y = 32 + }, +/turf/open/floor/plasteel/grimy, +/area/library) "wei" = ( /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, @@ -127564,6 +127052,38 @@ /obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white, /area/science/misc_lab) +"wEg" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/firealarm{ + dir = 1; + pixel_y = -26 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port) +"wFu" = ( +/obj/structure/lattice, +/obj/structure/grille, +/turf/open/space/basic, +/area/space/nearstation) +"wHv" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/green/visible, +/turf/open/floor/plasteel/dark, +/area/engine/atmos) "wIf" = ( /obj/item/twohanded/required/kirbyplants/random, /turf/open/floor/plasteel, @@ -127586,6 +127106,23 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) +"xbz" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "xdZ" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -127716,6 +127253,13 @@ /obj/structure/fans/tiny/invisible, /turf/open/space/basic, /area/space) +"yin" = ( +/obj/structure/chair/sofa/left{ + icon_state = "sofaend_left"; + dir = 8 + }, +/turf/open/floor/wood, +/area/library) "yiv" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral{ @@ -149940,22 +149484,22 @@ aNY aMB aMG aMG -aMG +aWN aWy -aMB -aZS -aMG +bol +emA +bol aWy -aMB -aZS -aMG -aWy -aMB -aZS -aMG -aZS -aMB +bol +emA +bol aWy +bol +emA +mxy +emA +vFd +aUP aMG aMG bxE @@ -150203,12 +149747,12 @@ aXY aZT bbA bda -aST +wHv bfU bhf -bda -aST -aZT +eRX +wHv +lqA bok bpQ brV @@ -150466,7 +150010,7 @@ bbB biW bkJ bmJ -bol +aTg bpR brW btN @@ -150706,20 +150250,20 @@ aGV aIv aJO aLj -aMB -aOa +aME +aOe aPF aRs aSV aUN aWB -aYa -aYa -aYa +aWB +aWB +aWB bdc -aYa -aYa -aYa +aWB +aWB +kQS biX bkK bmK @@ -150962,7 +150506,7 @@ aFr aGW aIw aJP -aLk +aLl aMB aOa aPG @@ -150970,17 +150514,17 @@ aRt aSW aUO aWC -aYb -aZV -aZV -bdd -bey -bae -bae +aWC +aWC +aWC +aWC +aWC +aWC +aYn biY bkL bmL -bom +bok bpT brY btP @@ -151220,20 +150764,20 @@ aFr aIx aJQ aLl -aME +aMB aOb aPH -aRu +aRy aSX -aUP -aWD -aYc -aZW -bbC -aYc -bez -bfW -aWD +aUO +aWC +aWC +aWC +aWC +aWC +aWC +aWC +aWC biZ bkM bmM @@ -151483,16 +151027,16 @@ aPI aRv aSW aUO -aWE -aYd -aZX -bbD -bde -bde +aWC +aWC +aWC +aWC +aWC +aWC bfX -bhg -bja -bkM +aWC +biZ +bkL bmN bon bpV @@ -151737,21 +151281,21 @@ aFr aMG aOd aPJ -aRw -aSY -aUP -aWF -aYe -aZY -bbE -bdf -bez -bfY -bhh -bjb +aRv +aSW +aUO +aWC +aWC +aWC +aWC +aWC +aWC +aWC +aWC +aYn bkN bmO -boo +aTg bpW bsb btS @@ -151992,20 +151536,20 @@ ayR aJT aLn aMG -aOe -aOo +aOn +aRu aRv aSW aUQ -aWG +aWC aYf -aZZ -aZZ -aZZ +aWC +aWC +aWC beA -aWK -bhi -bjc +aWC +aWC +aWC bkO bmP aTg @@ -152259,11 +151803,11 @@ aYg aMB aWH aMB -aWH +hwV aWH bhj bjd -bkP +bkO bmQ bop bpY @@ -152506,8 +152050,8 @@ aBf aJV aLp aMG -aOe -aOo +aOn +aRu aRv aSW aUS @@ -152520,12 +152064,12 @@ beB bfZ bhk bje -bkQ +bkN bmR boq bpZ bsd -aYn +boq bvf aMG bxL @@ -152777,7 +152321,7 @@ beC bga bhl bjf -bkP +oVn bmS bor bqa @@ -153020,7 +152564,7 @@ alT aJW aLq aMG -aOe +aOn aPN aRv aSW @@ -153801,7 +153345,7 @@ aYl bae bae bae -bae +xbz aWL bhp bji @@ -154053,7 +153597,7 @@ aPR aRB aTc aUV -aWM +bxS aYm baf bbJ @@ -154062,7 +153606,7 @@ baf baf bhq bjj -bkU +bkP bmX bow bqf @@ -154310,13 +153854,13 @@ aPS aRv aSW aUO -aWN +bxR +aYn aYn -bag aYn aYn beG -bgb +aYn bhr bjk bkV @@ -154569,10 +154113,10 @@ aTd aUW aWO aYo -aWO -bbK -bbK -beH +sby +aYo +aYo +aYo bgc bhs bjl @@ -155080,16 +154624,16 @@ aOo aOn aRD aTf -aOn -aRC +bkU +bnc aYq bai bbM bdl beJ bge -bhu -bdl +aXY +qej bkY bnb aMG @@ -155335,20 +154879,20 @@ alT aML aMG aMG -aMG -aTg +aRw +aUP aMB aTg -aMG -aWy +boo +aUP aMB aZS -aMG -aWy +boo +aUP aMB aZS -aMG -bnc +jaZ +aMB aMG bqk bsn @@ -155592,20 +155136,20 @@ aLy alT aad aad +aSY +aWM aRE aTh -aRE -aTh -aRE -aWx +cJl +lhL aRE aZR -aRE -aWx +cJl +lhL aRE aZR bkZ -aMN +aMM aMG bql bso @@ -157209,7 +156753,7 @@ cOM dgs cMY djE -dlr +dlq dmE dow dqm @@ -158716,7 +158260,7 @@ ccq ceg ccq chO -ceg +vLX ckQ cmr ccq @@ -158969,11 +158513,11 @@ bUt bWD bYM caH -ccr +cwq ceh -cfY -chP -cjt +caG +caG +oek ckR cms cnO @@ -159224,12 +158768,12 @@ bDl bDl bUu bWE -bYO +gjg caG -ccs -cei +mRS +cxV cfZ -chQ +caG cjt ckR cms @@ -159483,11 +159027,11 @@ bUv bWC bYR caG +jqs +cxV +gOM caG -caG -caG -chR -cjt +tDx ckR cmt cmt @@ -159740,10 +159284,10 @@ bUq bWI bYM caG -cct -cej +jqs +cxV +gOM caG -chS cjt ckR cms @@ -159997,11 +159541,11 @@ bUq bWD bYM caG -ccu -cek -cga -chT -cju +jqs +cxV +gOM +caG +cjt ckR cms cnQ @@ -160255,9 +159799,9 @@ bWD bYM caG ccv -cel +cxV +pLF caG -chU cjt ckR xuu @@ -160511,9 +160055,9 @@ bUq bWD bYS caG -caG -caG -caG +jVB +cxV +cmt chV cjt ckT @@ -160770,7 +160314,7 @@ bYM caG cct cej -caG +cxV chW cjt ckR @@ -161026,12 +160570,12 @@ bWD bYM caG ccu -cek -cga -chT -cju +cmt +cmt +ccr +cjt ckR -cmv +cmt cnU cpy cqT @@ -161280,11 +160824,11 @@ bQu bQv bUr bWD -bYM +wEg caG -ccv +chP cel -caG +yin chX cjt ckR @@ -173572,7 +173116,7 @@ azG aAI aCb aDf -aEh +avW aFk aGD aHW @@ -178522,7 +178066,7 @@ cDD cFx cGU cAw -cJl +cJk cLa cMx cIi @@ -182598,7 +182142,7 @@ buU biQ aad ajr -ajr +wFu aad ajr ajr diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index a18d3ab68e..7859d735d6 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -2562,6 +2562,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 10 }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/security/execution/transfer) "afu" = ( @@ -2890,6 +2891,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 6 }, +/obj/machinery/space_heater, /turf/open/floor/plasteel, /area/security/main) "agb" = ( @@ -3804,8 +3806,6 @@ }, /obj/structure/closet/wardrobe/white, /obj/item/clothing/under/suit/waiter, -/obj/item/clothing/under/suit/waiter, -/obj/item/clothing/under/suit/waiter, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "ahD" = ( @@ -3938,24 +3938,18 @@ /turf/open/floor/plasteel, /area/security/main) "ahO" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 4; - pixel_y = 5 - }, /obj/structure/chair/sofa/left{ dir = 1 }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 4 + }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "ahP" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/closet/wardrobe/mixed, /obj/item/clothing/under/costume/kilt, -/obj/item/clothing/under/costume/kilt, -/obj/item/clothing/under/dress/skirt/purple, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/beret, /obj/structure/sign/poster/official/fashion{ pixel_x = -32 }, @@ -4486,13 +4480,13 @@ /turf/open/floor/plating, /area/maintenance/fore/secondary) "aiB" = ( -/obj/machinery/vending/kink, /obj/structure/disposalpipe/segment{ dir = 4 }, /obj/structure/sign/poster/official/fashion{ pixel_y = 32 }, +/obj/machinery/vending/autodrobe, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aiC" = ( @@ -4516,6 +4510,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 9 }, +/obj/machinery/space_heater, /turf/open/floor/plasteel, /area/security/processing) "aiE" = ( @@ -6246,6 +6241,7 @@ /obj/structure/sign/warning/vacuum/external{ pixel_x = 32 }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/solars/port/fore) "alT" = ( @@ -7243,6 +7239,7 @@ /obj/machinery/light/small{ dir = 1 }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/port/fore) "aok" = ( @@ -7470,6 +7467,7 @@ /obj/structure/disposalpipe/segment{ dir = 9 }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/fore/secondary) "aoJ" = ( @@ -7480,12 +7478,10 @@ /obj/machinery/light/small{ dir = 8 }, -/obj/structure/chair/stool{ - pixel_y = 8 - }, /obj/effect/turf_decal/stripes/line{ dir = 9 }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/fore/secondary) "aoL" = ( @@ -7599,10 +7595,10 @@ /turf/open/floor/plating, /area/security/warden) "apa" = ( -/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ - dir = 4 - }, /obj/machinery/meter, +/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "apb" = ( @@ -9081,6 +9077,10 @@ dir = 8; pixel_x = 28 }, +/obj/machinery/space_heater{ + desc = "For when you got to turn up the heat on the suspect, or cool down your partners hot temper"; + name = "The Griller" + }, /turf/open/floor/plasteel/dark, /area/security/brig) "asq" = ( @@ -9628,6 +9628,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/space_heater, /turf/open/floor/plasteel, /area/construction/mining/aux_base) "aud" = ( @@ -10036,7 +10037,7 @@ name = "Cargo Bay"; width = 12 }, -/turf/closed/mineral/random/snow/no_caves, +/turf/open/floor/plating/asteroid/snow/icemoon, /area/icemoon/surface/outdoors) "avf" = ( /obj/structure/sign/warning/docking{ @@ -10738,21 +10739,7 @@ /obj/structure/closet{ name = "Holodeck Outfits" }, -/obj/item/clothing/under/trek/Q, -/obj/item/clothing/under/trek/command/next, -/obj/item/clothing/under/trek/command/next, -/obj/item/clothing/under/trek/command/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/engsec/next, -/obj/item/clothing/under/trek/medsci/next, -/obj/item/clothing/under/trek/medsci/next, -/obj/item/clothing/under/trek/medsci/next, /obj/item/clothing/under/misc/blue_camo, -/obj/item/clothing/under/misc/blue_camo, -/obj/item/clothing/under/costume/gladiator, -/obj/item/clothing/under/costume/gladiator, /obj/machinery/firealarm{ dir = 4; pixel_x = -24 @@ -12277,6 +12264,7 @@ dir = 1 }, /obj/effect/turf_decal/stripes/line, +/obj/machinery/space_heater, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "aAI" = ( @@ -14109,8 +14097,7 @@ /area/crew_quarters/dorms) "aFk" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 4; - pixel_y = 5 + dir = 4 }, /turf/open/floor/wood, /area/crew_quarters/bar) @@ -14603,13 +14590,12 @@ /turf/closed/wall, /area/crew_quarters/theatre) "aGw" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 4; - pixel_y = 5 - }, /obj/machinery/light/small{ dir = 4 }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, /turf/open/floor/wood, /area/crew_quarters/bar) "aGx" = ( @@ -15250,10 +15236,6 @@ /turf/open/floor/plasteel, /area/crew_quarters/dorms) "aHV" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 1; - pixel_x = 5 - }, /obj/machinery/light/small{ dir = 4 }, @@ -15266,6 +15248,9 @@ /obj/item/reagent_containers/rag/towel/random, /obj/item/reagent_containers/rag/towel/random, /obj/item/reagent_containers/rag/towel/random, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, /turf/open/floor/mineral/titanium/blue, /area/crew_quarters/toilet) "aHY" = ( @@ -15291,6 +15276,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 5 }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/starboard/fore) "aIc" = ( @@ -16873,10 +16859,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/structure/sign/poster/contraband/robust_softdrinks{ - pixel_x = -32; - pixel_y = 32 - }, /turf/open/floor/plasteel, /area/hallway/primary/central) "aMh" = ( @@ -18099,7 +18081,6 @@ /obj/structure/cable{ icon_state = "0-8" }, -/obj/machinery/status_display/evac, /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/preopen{ id = "bridge blast"; @@ -18124,21 +18105,6 @@ }, /turf/open/floor/plating, /area/bridge) -"aPW" = ( -/obj/structure/cable{ - icon_state = "0-8" - }, -/obj/structure/cable{ - icon_state = "0-4" - }, -/obj/machinery/status_display/evac, -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/door/poddoor/preopen{ - id = "bridge blast"; - name = "bridge blast door" - }, -/turf/open/floor/plating, -/area/bridge) "aPX" = ( /obj/structure/cable{ icon_state = "0-8" @@ -18462,7 +18428,6 @@ /obj/structure/closet/wardrobe/white, /obj/item/clothing/suit/ghost_sheet, /obj/item/clothing/suit/ghost_sheet, -/obj/item/clothing/suit/ghost_sheet, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQP" = ( @@ -18490,10 +18455,10 @@ /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQV" = ( -/obj/machinery/vending/autodrobe/all_access, /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/machinery/vending/clothing, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQW" = ( @@ -18507,7 +18472,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/machinery/vending/games, +/obj/machinery/vending/kink, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aQY" = ( @@ -18990,9 +18955,6 @@ name = "Station Intercom (General)"; pixel_x = -27 }, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/beret, -/obj/item/clothing/head/russobluecamohat, /obj/item/clothing/head/russobluecamohat, /turf/open/floor/plasteel, /area/crew_quarters/locker) @@ -19304,15 +19266,16 @@ name = "Art Storage"; pixel_y = 24 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, /obj/structure/cable{ icon_state = "0-8" }, /obj/structure/cable{ icon_state = "4-8" }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plating, /area/maintenance/port) "aSY" = ( @@ -19475,7 +19438,6 @@ dir = 8 }, /obj/item/clothing/under/costume/kilt, -/obj/item/clothing/under/costume/kilt, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aTy" = ( @@ -19851,6 +19813,7 @@ dir = 1 }, /obj/machinery/light/small, +/obj/machinery/space_heater, /turf/open/floor/plasteel, /area/storage/tools) "aUx" = ( @@ -19993,13 +19956,8 @@ department = "Locker Room"; pixel_x = -32 }, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/color/grey, -/obj/item/clothing/under/color/grey, /turf/open/floor/plasteel, -/area/crew_quarters/locker) +/area/space) "aUW" = ( /obj/structure/table/wood, /obj/item/flashlight/lamp/green, @@ -20608,13 +20566,6 @@ "aWn" = ( /obj/structure/closet/wardrobe/black, /obj/item/clothing/shoes/jackboots, -/obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/under/costume/maid, -/obj/item/clothing/under/costume/maid, -/obj/item/clothing/accessory/maidapron, -/obj/item/clothing/accessory/maidapron, -/obj/item/clothing/head/beret/black, /obj/item/clothing/head/beret/black, /turf/open/floor/plasteel, /area/crew_quarters/locker) @@ -21958,19 +21909,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/wood, /area/security/vacantoffice) -"aZo" = ( -/obj/structure/sink{ - dir = 4; - pixel_x = 11 - }, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 1 - }, -/obj/structure/mirror{ - pixel_x = 28 - }, -/turf/open/floor/plasteel/freezer, -/area/crew_quarters/toilet/locker) "aZp" = ( /obj/structure/rack, /obj/item/electronics/apc, @@ -22041,6 +21979,7 @@ /area/crew_quarters/toilet/locker) "aZw" = ( /obj/effect/landmark/blobstart, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "aZx" = ( @@ -22399,6 +22338,7 @@ c_tag = "Locker Room Toilets"; dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "bax" = ( @@ -22725,9 +22665,7 @@ /obj/machinery/light{ dir = 8 }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 1 - }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/locker) "bbs" = ( @@ -23094,9 +23032,11 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard) "bct" = ( -/obj/structure/chair/wood/wings, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 1 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "bcu" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/door/airlock/maintenance{ @@ -23573,9 +23513,12 @@ /turf/open/floor/carpet, /area/bridge/meeting_room) "bdJ" = ( -/obj/structure/closet/secure_closet/personal/cabinet, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/door/airlock{ + id_tag = "LockerShitter3"; + name = "Unit 3" + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "bdK" = ( /obj/machinery/holopad, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -24142,12 +24085,8 @@ /turf/closed/wall, /area/maintenance/disposal) "bfa" = ( -/obj/structure/closet/crate, -/obj/item/stack/sheet/mineral/wood/fifty{ - amount = 20 - }, -/turf/open/floor/plating, -/area/maintenance/port) +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "bfb" = ( /obj/structure/sign/warning/vacuum/external{ pixel_y = 32 @@ -24182,7 +24121,6 @@ /area/maintenance/port) "bfe" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/structure/reagent_dispensers/watertank, /turf/open/floor/plating, /area/maintenance/port) "bff" = ( @@ -24556,7 +24494,7 @@ dir = 1 }, /obj/effect/turf_decal/stripes/line, -/obj/effect/landmark/start/assistant, +/obj/machinery/space_heater, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "bgj" = ( @@ -24623,16 +24561,15 @@ /turf/open/floor/plating, /area/maintenance/port) "bgr" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on, -/turf/open/floor/plating, -/area/maintenance/port) -"bgs" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/obj/structure/table/wood/fancy/purple, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/door/airlock{ + id_tag = "LockerShitter4"; + name = "Unit 4" + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "bgt" = ( /obj/effect/spawner/lootdrop/maintenance, +/obj/structure/reagent_dispensers/watertank, /turf/open/floor/plating, /area/maintenance/port) "bgu" = ( @@ -24762,6 +24699,7 @@ /obj/machinery/computer/security/telescreen/entertainment{ pixel_y = -32 }, +/obj/machinery/space_heater, /turf/open/floor/wood, /area/bridge/meeting_room) "bgM" = ( @@ -24888,9 +24826,6 @@ /obj/machinery/camera{ c_tag = "Chemistry" }, -/obj/machinery/firealarm{ - pixel_y = 24 - }, /obj/machinery/chem_heater, /turf/open/floor/plasteel/white, /area/medical/chemistry) @@ -25248,7 +25183,7 @@ dir = 4 }, /turf/closed/wall, -/area/maintenance/port) +/area/crew_quarters/toilet/locker) "bhR" = ( /obj/structure/grille, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -27005,6 +26940,7 @@ /area/crew_quarters/dorms) "blV" = ( /obj/machinery/light/small, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/disposal) "blW" = ( @@ -27915,6 +27851,10 @@ /obj/machinery/light{ dir = 8 }, +/obj/machinery/firealarm{ + dir = 4; + pixel_x = -24 + }, /turf/open/floor/plasteel/white, /area/medical/chemistry) "boc" = ( @@ -29375,14 +29315,7 @@ /turf/open/floor/plating, /area/maintenance/starboard) "brz" = ( -/obj/structure/table, -/obj/item/pen, -/obj/machinery/camera{ - c_tag = "Experimentor Lab"; - network = list("ss13","rd") - }, -/obj/item/hand_labeler, -/obj/item/stack/packageWrap, +/obj/machinery/rnd/bepis, /turf/open/floor/plasteel/white/side, /area/science/explab) "brA" = ( @@ -29404,6 +29337,10 @@ pixel_y = 23 }, /obj/item/radio/off, +/obj/machinery/camera{ + c_tag = "Experimentor Lab"; + network = list("ss13","rd") + }, /turf/open/floor/plasteel/white/side, /area/science/explab) "brD" = ( @@ -32894,6 +32831,7 @@ /obj/structure/cable{ icon_state = "0-8" }, +/obj/machinery/space_heater, /turf/open/floor/plasteel/dark, /area/science/server) "bzz" = ( @@ -35616,8 +35554,7 @@ pixel_y = 3 }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 4; - pixel_y = 5 + dir = 4 }, /turf/open/floor/wood, /area/crew_quarters/bar) @@ -36528,6 +36465,7 @@ department = "Tech storage"; pixel_y = -32 }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/storage/tech) "bHO" = ( @@ -37657,6 +37595,7 @@ /area/quartermaster/miningdock) "bKo" = ( /obj/machinery/light, +/obj/machinery/space_heater, /turf/open/floor/plasteel, /area/quartermaster/miningdock) "bKp" = ( @@ -38326,7 +38265,7 @@ /obj/machinery/light/small{ dir = 8 }, -/obj/machinery/chem_dispenser, +/obj/machinery/chem_dispenser/apothecary, /turf/open/floor/plasteel/white, /area/medical/medbay/central) "bLV" = ( @@ -38521,9 +38460,13 @@ /turf/open/floor/plating, /area/science/xenobiology) "bMs" = ( -/obj/effect/spawner/structure/window/reinforced, +/obj/effect/spawner/lootdrop/maintenance{ + lootcount = 2; + name = "2maintenance loot spawner" + }, +/obj/machinery/space_heater, /turf/open/floor/plating, -/area/science/research) +/area/maintenance/fore/secondary) "bMt" = ( /obj/structure/sign/warning/vacuum/external{ pixel_y = 32 @@ -38667,11 +38610,20 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bMM" = ( -/obj/machinery/atmospherics/components/unary/thermomachine/heater, +/obj/structure/rack, +/obj/item/clothing/suit/hazardvest, +/obj/item/clothing/suit/hazardvest, +/obj/item/clothing/suit/hazardvest, +/obj/item/clothing/suit/hazardvest, +/obj/item/clothing/gloves/color/black, +/obj/item/clothing/gloves/color/black, +/obj/item/clothing/gloves/color/black, +/obj/item/clothing/mask/gas, +/obj/item/clothing/mask/gas, /turf/open/floor/plasteel, /area/engine/atmos) "bMN" = ( -/obj/machinery/atmospherics/components/unary/thermomachine/freezer, +/obj/machinery/atmospherics/components/unary/thermomachine/heater, /turf/open/floor/plasteel, /area/engine/atmos) "bMO" = ( @@ -38741,15 +38693,13 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bMY" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 4 +/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ + dir = 1 }, -/turf/closed/wall/r_wall, +/turf/open/floor/plasteel, /area/engine/atmos) "bMZ" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 6 - }, +/obj/machinery/atmospherics/components/unary/thermomachine/heater/on, /turf/open/floor/plasteel, /area/engine/atmos) "bNc" = ( @@ -39077,6 +39027,9 @@ /obj/machinery/light{ dir = 8 }, +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bNU" = ( @@ -39138,7 +39091,7 @@ /area/engine/atmos) "bOe" = ( /obj/machinery/meter, -/obj/machinery/atmospherics/pipe/manifold4w/cyan/visible, +/obj/machinery/atmospherics/pipe/manifold/cyan/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bOf" = ( @@ -39149,13 +39102,7 @@ /turf/open/floor/plating, /area/engine/atmos) "bOg" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1; - name = "Mix to Incinerator" - }, +/obj/machinery/atmospherics/pipe/manifold/cyan/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bOh" = ( @@ -39462,17 +39409,16 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bOR" = ( -/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ +/obj/machinery/meter, +/obj/machinery/atmospherics/pipe/manifold/purple/visible{ dir = 1 }, -/obj/machinery/meter, /turf/open/floor/plasteel, /area/engine/atmos) "bOS" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 6 }, -/obj/structure/tank_dispenser, /turf/open/floor/plasteel, /area/engine/atmos) "bOT" = ( @@ -39485,8 +39431,8 @@ /area/engine/atmos) "bOU" = ( /obj/machinery/holopad, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -39573,35 +39519,34 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bPe" = ( -/obj/machinery/atmospherics/pipe/manifold/yellow/visible, +/obj/machinery/atmospherics/pipe/manifold/purple/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bPf" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ +/obj/machinery/atmospherics/pipe/simple/purple/visible{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bPg" = ( -/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/purple/visible{ + dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bPh" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible, -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/layer_manifold{ dir = 4 }, -/obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/engine/atmos) "bPi" = ( /obj/machinery/light{ dir = 4 }, -/obj/machinery/atmospherics/pipe/manifold/yellow/visible, /obj/effect/turf_decal/tile/green{ dir = 1 }, @@ -39609,6 +39554,9 @@ /obj/effect/turf_decal/tile/green{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/purple/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bPj" = ( @@ -40032,8 +39980,8 @@ /obj/machinery/computer/atmos_alert{ dir = 8 }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 }, /turf/open/floor/plasteel/dark/corner, /area/engine/atmos) @@ -40047,7 +39995,11 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/spawner/structure/window, +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/preopen{ + id = "atmos"; + name = "Atmospherics Blast Door" + }, /turf/open/floor/plating, /area/engine/atmos) "bQo" = ( @@ -40091,7 +40043,7 @@ /turf/open/floor/plasteel, /area/security/checkpoint/engineering) "bQr" = ( -/obj/structure/closet/crate, +/obj/machinery/atmospherics/components/unary/thermomachine/freezer, /turf/open/floor/plasteel, /area/engine/atmos) "bQs" = ( @@ -40115,38 +40067,31 @@ /turf/open/floor/plasteel/dark/corner, /area/hallway/primary/aft) "bQu" = ( -/obj/structure/rack, -/obj/item/clothing/suit/hazardvest, -/obj/item/clothing/suit/hazardvest, -/obj/item/clothing/suit/hazardvest, -/obj/item/clothing/suit/hazardvest, -/obj/item/clothing/gloves/color/black, -/obj/item/clothing/gloves/color/black, -/obj/item/clothing/gloves/color/black, -/obj/item/clothing/mask/gas, -/obj/item/clothing/mask/gas, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/closet/crate, /turf/open/floor/plasteel, /area/engine/atmos) "bQv" = ( +/obj/machinery/atmospherics/pipe/simple/purple/visible, /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bQw" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 9 +/obj/machinery/atmospherics/pipe/manifold/green/visible{ + dir = 1 }, /turf/open/floor/plasteel, /area/engine/atmos) "bQx" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 6 }, -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1; - name = "Mix to Distro" +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 9 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -40163,6 +40108,9 @@ /obj/effect/turf_decal/tile/green{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 10 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bQA" = ( @@ -40438,6 +40386,11 @@ /area/hallway/primary/aft) "bRr" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/firealarm{ + dir = 1; + pixel_y = -24 + }, +/obj/structure/tank_dispenser, /turf/open/floor/plasteel, /area/engine/atmos) "bRs" = ( @@ -40449,11 +40402,7 @@ /turf/open/floor/plating, /area/engine/atmos) "bRt" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/firealarm{ - dir = 1; - pixel_y = -24 - }, +/obj/structure/reagent_dispensers/fueltank, /turf/open/floor/plasteel, /area/engine/atmos) "bRu" = ( @@ -40463,7 +40412,6 @@ /obj/machinery/computer/atmos_alert{ dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/dark/corner, /area/engine/atmos) "bRv" = ( @@ -40482,8 +40430,10 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bRx" = ( -/obj/effect/spawner/structure/window, -/turf/open/floor/plating, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ + dir = 1 + }, +/turf/open/floor/plasteel, /area/engine/atmos) "bRy" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ @@ -40501,8 +40451,9 @@ /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 4 +/obj/machinery/atmospherics/components/binary/pump/on{ + dir = 8; + name = "Waste to Filter" }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -40518,26 +40469,26 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bRD" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 9 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bRE" = ( -/obj/machinery/atmospherics/pipe/manifold/green/visible{ - dir = 1 +/obj/machinery/atmospherics/components/binary/pump{ + name = "Air to Ports" }, -/obj/machinery/meter, /turf/open/floor/plasteel, /area/engine/atmos) "bRF" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 4 +/obj/machinery/atmospherics/components/binary/pump{ + name = "Mix to Ports" }, -/obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bRG" = ( -/obj/machinery/atmospherics/pipe/manifold/green/visible{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 5 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -40554,6 +40505,14 @@ dir = 4; name = "Unfiltered & Air to Mix" }, +/obj/machinery/atmospherics/pipe/simple/green/visible, +/obj/effect/turf_decal/tile/green{ + dir = 8 + }, +/obj/effect/turf_decal/tile/green, +/obj/effect/turf_decal/tile/green{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bRL" = ( @@ -40841,11 +40800,7 @@ /area/hallway/primary/aft) "bSB" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/machinery/door/airlock/atmos/glass{ - name = "Atmospherics Monitoring"; - req_access_txt = "24" - }, -/turf/open/floor/plasteel, +/turf/closed/wall, /area/engine/atmos) "bSC" = ( /obj/machinery/atmospherics/pipe/simple/orange/visible{ @@ -40855,13 +40810,19 @@ /area/engine/atmos) "bSD" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/closed/wall, +/obj/machinery/door/airlock/atmos/glass{ + name = "Atmospherics Monitoring"; + req_access_txt = "24" + }, +/obj/machinery/door/firedoor/heavy, +/turf/open/floor/plasteel, /area/engine/atmos) "bSE" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 5 +/obj/machinery/atmospherics/components/binary/pump{ + dir = 1; + name = "Pure to Mix" }, -/turf/closed/wall, +/turf/open/floor/plasteel, /area/engine/atmos) "bSF" = ( /obj/effect/turf_decal/bot, @@ -40893,13 +40854,15 @@ /area/engine/atmos) "bSM" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/yellow/visible, +/obj/machinery/atmospherics/pipe/simple/general/visible{ + dir = 5 + }, /turf/open/floor/plating, /area/engine/atmos) "bSN" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 5 +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 10 }, /turf/open/floor/plating, /area/engine/atmos) @@ -41237,7 +41200,12 @@ /obj/machinery/atmospherics/pipe/simple/orange/visible{ dir = 4 }, -/turf/open/floor/plasteel, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/turf/open/floor/plasteel/dark/corner{ + dir = 1 + }, /area/engine/atmos) "bTM" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -41250,14 +41218,16 @@ /obj/machinery/atmospherics/pipe/simple/orange/visible{ dir = 4 }, -/obj/effect/spawner/structure/window, /turf/open/floor/plasteel, /area/engine/atmos) "bTO" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 1; + name = "External to Waste" + }, /turf/open/floor/plasteel, /area/engine/atmos) "bTP" = ( @@ -41267,19 +41237,14 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bTQ" = ( -/obj/machinery/atmospherics/components/binary/pump/on{ - dir = 8; - name = "Waste to Filter" +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 5 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, -/turf/open/floor/plasteel, +/turf/open/floor/plating, /area/engine/atmos) "bTR" = ( -/obj/machinery/atmospherics/components/binary/pump/on{ - dir = 8; - name = "Filter to Waste" - }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, +/obj/machinery/atmospherics/pipe/manifold/orange/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bTS" = ( @@ -41287,15 +41252,16 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bTU" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 5 +/obj/machinery/atmospherics/components/binary/pump{ + dir = 8; + name = "Pure to Ports" }, /turf/open/floor/plasteel, /area/engine/atmos) "bTV" = ( /obj/machinery/atmospherics/components/binary/pump{ dir = 8; - name = "N2O Outlet Pump" + name = "N2O to Pure" }, /obj/effect/turf_decal/tile/red{ dir = 4 @@ -41641,7 +41607,9 @@ /area/engine/atmos) "bUL" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/green/visible, +/obj/machinery/atmospherics/pipe/manifold/general/visible{ + dir = 4 + }, /turf/open/floor/plating, /area/engine/atmos) "bUM" = ( @@ -41655,9 +41623,7 @@ /area/engine/atmos) "bUN" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 10 - }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plating, /area/engine/atmos) "bUO" = ( @@ -41683,7 +41649,7 @@ icon_state = "1-2" }, /obj/machinery/atmospherics/pipe/simple/cyan/visible, -/obj/machinery/atmospherics/components/binary/pump/on{ +/obj/machinery/atmospherics/components/binary/pump{ dir = 8; name = "Mix to External" }, @@ -41697,6 +41663,9 @@ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/green/visible, +/obj/machinery/atmospherics/pipe/simple/dark/visible{ + dir = 4 + }, /turf/open/floor/plasteel/white/corner, /area/engine/atmos) "bUU" = ( @@ -42025,10 +41994,10 @@ /turf/closed/wall/r_wall, /area/engine/atmos) "bVP" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 6 +/obj/machinery/atmospherics/components/binary/pump{ + dir = 8; + name = "External to Pumps" }, -/obj/effect/spawner/structure/window, /turf/open/floor/plasteel, /area/engine/atmos) "bVQ" = ( @@ -42124,6 +42093,12 @@ /obj/machinery/atmospherics/components/trinary/filter/atmos/n2o{ dir = 1 }, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, /turf/open/floor/plasteel/white/corner, /area/engine/atmos) "bWd" = ( @@ -42404,7 +42379,12 @@ dir = 4; pixel_x = -22 }, -/turf/open/floor/plasteel, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/turf/open/floor/plasteel/dark/corner{ + dir = 1 + }, /area/engine/atmos) "bWO" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ @@ -42413,8 +42393,10 @@ /turf/closed/wall/r_wall, /area/engine/atmos) "bWP" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, -/turf/closed/wall, +/obj/machinery/atmospherics/pipe/manifold/general/visible{ + dir = 1 + }, +/turf/open/floor/plasteel, /area/engine/atmos) "bWQ" = ( /turf/closed/wall/r_wall, @@ -42438,7 +42420,7 @@ /obj/structure/cable{ icon_state = "1-4" }, -/turf/open/floor/plating, +/turf/open/floor/plasteel, /area/engine/atmos) "bWU" = ( /obj/machinery/light{ @@ -42776,7 +42758,12 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ dir = 9 }, -/turf/closed/wall, +/obj/machinery/door/poddoor/preopen{ + id = "atmos"; + name = "Atmospherics Blast Door" + }, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, /area/engine/atmos) "bXM" = ( /obj/machinery/door/poddoor/preopen{ @@ -42855,7 +42842,10 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bXU" = ( -/obj/structure/reagent_dispensers/fueltank, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 8; + name = "Ports to External" + }, /turf/open/floor/plasteel, /area/engine/atmos) "bXV" = ( @@ -42865,12 +42855,19 @@ }, /obj/machinery/atmospherics/components/binary/pump{ dir = 8; - name = "Plasma Outlet Pump" + name = "Plasma to Pure" }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /obj/effect/turf_decal/stripes/line{ dir = 5 }, -/obj/machinery/atmospherics/pipe/simple/green/visible, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bXW" = ( @@ -43074,6 +43071,7 @@ /obj/structure/sign/warning/vacuum/external{ pixel_x = -32 }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/port/aft) "bYv" = ( @@ -43173,17 +43171,8 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "bYJ" = ( -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/obj/machinery/door/airlock/atmos{ - name = "Atmospherics"; - req_access_txt = "24" - }, -/obj/machinery/door/firedoor/heavy, -/turf/open/floor/plasteel/dark/corner{ - dir = 1 - }, +/obj/machinery/atmospherics/pipe/manifold4w/general/visible, +/turf/open/floor/plasteel, /area/engine/atmos) "bYK" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible, @@ -43216,11 +43205,8 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "bYN" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 4 - }, -/turf/open/floor/plating, +/obj/machinery/atmospherics/pipe/manifold4w/yellow/visible, +/turf/open/floor/plasteel, /area/engine/atmos) "bYO" = ( /obj/structure/disposalpipe/segment{ @@ -43236,10 +43222,14 @@ /obj/machinery/computer/atmos_control/tank/toxin_tank{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, /obj/effect/turf_decal/stripes/line{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/green/visible, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel, /area/engine/atmos) "bYU" = ( @@ -43540,16 +43530,32 @@ /area/engine/atmos) "bZH" = ( /obj/machinery/portable_atmospherics/canister, +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bZI" = ( -/obj/machinery/portable_atmospherics/scrubber, +/obj/machinery/space_heater, +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bZK" = ( /obj/machinery/atmospherics/components/trinary/filter/atmos/plasma{ dir = 1 }, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bZL" = ( @@ -43602,6 +43608,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 9 }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/aft) "bZS" = ( @@ -43933,13 +43940,18 @@ /turf/closed/wall/r_wall, /area/security/checkpoint/engineering) "caE" = ( -/obj/structure/reagent_dispensers/watertank/high, +/obj/machinery/atmospherics/pipe/manifold/general/visible{ + dir = 8 + }, /turf/open/floor/plasteel, /area/engine/atmos) "caF" = ( /obj/machinery/atmospherics/pipe/simple/green/visible{ dir = 6 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 9 + }, /turf/open/floor/plasteel, /area/engine/atmos) "caG" = ( @@ -43953,12 +43965,10 @@ /turf/open/floor/plasteel, /area/engine/atmos) "caH" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 5 - }, /obj/effect/decal/cleanable/oil{ icon_state = "floor6" }, +/obj/machinery/atmospherics/pipe/manifold/yellow/visible, /turf/open/floor/plasteel, /area/engine/atmos) "caI" = ( @@ -44366,14 +44376,17 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "cbA" = ( -/obj/machinery/portable_atmospherics/pump, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 4; + name = "Ports to Incinerator" + }, /turf/open/floor/plasteel, /area/engine/atmos) "cbB" = ( /obj/machinery/atmospherics/pipe/simple/green/visible, /obj/machinery/atmospherics/components/binary/pump{ dir = 8; - name = "Air Outlet Pump" + name = "Air to Pure" }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -44407,7 +44420,7 @@ "cbG" = ( /obj/machinery/atmospherics/components/binary/pump{ dir = 8; - name = "CO2 Outlet Pump" + name = "CO2 to Pure" }, /obj/effect/turf_decal/tile/yellow{ dir = 1 @@ -44640,8 +44653,6 @@ /turf/open/floor/plasteel/dark/telecomms, /area/tcommsat/server) "cci" = ( -/obj/structure/table, -/obj/item/multitool, /obj/effect/turf_decal/tile/yellow{ dir = 1 }, @@ -44651,6 +44662,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/space_heater, /turf/open/floor/plasteel, /area/tcommsat/computer) "ccj" = ( @@ -44784,7 +44796,10 @@ /turf/closed/wall/r_wall, /area/engine/engineering) "ccy" = ( -/obj/machinery/space_heater, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, +/obj/machinery/atmospherics/pipe/simple/dark/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "ccz" = ( @@ -45133,15 +45148,24 @@ /turf/open/floor/plating/snowed/smoothed/icemoon, /area/engine/atmos) "cdB" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 9 +/obj/machinery/atmospherics/pipe/simple/cyan/visible, +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/dark/visible{ + dir = 4 }, -/turf/open/floor/plasteel, +/turf/open/floor/plating, /area/engine/atmos) "cdC" = ( /obj/machinery/atmospherics/components/trinary/filter/atmos/co2{ dir = 1 }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/yellow, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "cdD" = ( @@ -45202,6 +45226,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 5 }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/aft) "cdK" = ( @@ -45328,6 +45353,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/item/multitool, /turf/open/floor/plasteel, /area/tcommsat/computer) "cef" = ( @@ -45734,7 +45760,10 @@ /turf/open/floor/plasteel, /area/engine/break_room) "cfi" = ( -/obj/machinery/portable_atmospherics/scrubber/huge, +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, +/obj/structure/reagent_dispensers/watertank/high, /turf/open/floor/plasteel, /area/engine/atmos) "cfj" = ( @@ -46028,6 +46057,7 @@ pixel_y = 26 }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/space_heater, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) "cga" = ( @@ -46229,6 +46259,7 @@ /obj/structure/sign/warning/vacuum/external{ pixel_x = -32 }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/solars/port/aft) "cgB" = ( @@ -46425,6 +46456,13 @@ /obj/machinery/atmospherics/components/trinary/filter/atmos/o2{ dir = 4 }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "chb" = ( @@ -46467,8 +46505,11 @@ /turf/open/floor/plasteel/cafeteria, /area/engine/atmos) "che" = ( -/obj/machinery/door/airlock/atmos{ - name = "Atmospherics"; +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/obj/machinery/door/airlock/external{ + name = "Atmospherics External Airlock"; req_access_txt = "24" }, /turf/open/floor/plating, @@ -46939,8 +46980,8 @@ /turf/closed/wall/r_wall, /area/engine/atmos) "ciu" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible, /obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/layer_manifold, /turf/open/floor/plating, /area/engine/atmos) "civ" = ( @@ -48242,8 +48283,6 @@ "clO" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/closet/wardrobe/grey, -/obj/item/clothing/under/misc/assistantformal, -/obj/item/clothing/under/misc/assistantformal, /obj/machinery/camera{ c_tag = "Dorms East - Holodeck"; dir = 4 @@ -48404,6 +48443,7 @@ /obj/structure/sign/warning/vacuum/external{ pixel_y = -32 }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/solars/starboard/aft) "cmy" = ( @@ -48774,6 +48814,7 @@ /obj/structure/disposalpipe/junction/flip{ dir = 4 }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/aft) "cnF" = ( @@ -49443,6 +49484,7 @@ c_tag = "Engineering Escape Pod"; dir = 4 }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/engine/engineering) "cqr" = ( @@ -49507,6 +49549,7 @@ /obj/machinery/light/small{ dir = 4 }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/port/aft) "cqM" = ( @@ -49626,6 +49669,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 5 }, +/obj/machinery/space_heater, /turf/open/floor/plasteel, /area/engine/engineering) "cry" = ( @@ -49845,6 +49889,7 @@ pixel_y = -29 }, /obj/machinery/light/small, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/ai_monitored/turret_protected/aisat_interior) "cti" = ( @@ -49863,6 +49908,7 @@ }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on, /obj/machinery/light/small, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/ai_monitored/turret_protected/aisat_interior) "ctk" = ( @@ -51425,6 +51471,7 @@ dir = 8 }, /obj/machinery/light/small, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/hallway/secondary/entry) "cxm" = ( @@ -51471,6 +51518,7 @@ dir = 8 }, /obj/machinery/light/small, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/hallway/secondary/entry) "cya" = ( @@ -52095,24 +52143,15 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard) "cBn" = ( -/obj/structure/closet, -/obj/item/stack/tile/carpet/royalblue{ - amount = 24 +/obj/structure/sink{ + dir = 4; + pixel_x = 11 }, -/obj/item/stack/tile/carpet/green{ - amount = 24 +/obj/structure/mirror{ + pixel_x = 28 }, -/obj/item/stack/tile/carpet/purple{ - amount = 24 - }, -/obj/item/stack/tile/carpet/orange{ - amount = 24 - }, -/obj/item/stack/tile/wood{ - amount = 24 - }, -/turf/open/floor/plating, -/area/maintenance/port) +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "cBo" = ( /obj/effect/landmark/event_spawn, /turf/open/floor/wood, @@ -52231,7 +52270,9 @@ /area/science/mixing) "cBF" = ( /obj/effect/landmark/event_spawn, -/obj/machinery/atmospherics/pipe/manifold4w/scrubbers/visible, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ + dir = 8 + }, /turf/open/floor/plasteel, /area/engine/atmos) "cBH" = ( @@ -52420,10 +52461,10 @@ /turf/open/floor/plating, /area/maintenance/starboard/aft) "cCE" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ +/obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/open/floor/plasteel, /area/engine/atmos) "cCF" = ( @@ -52516,10 +52557,7 @@ /turf/open/floor/wood, /area/crew_quarters/theatre) "cGG" = ( -/obj/effect/spawner/structure/window, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10 - }, +/obj/machinery/atmospherics/pipe/simple/general/visible, /turf/open/floor/plasteel, /area/engine/atmos) "cHf" = ( @@ -52901,10 +52939,6 @@ }, /turf/open/floor/plating/asteroid/snow/ice/icemoon/solarpanel, /area/icemoon/surface/outdoors) -"cMS" = ( -/obj/item/chair/wood, -/turf/open/floor/plating, -/area/maintenance/port) "cNa" = ( /obj/structure/cable, /obj/machinery/power/solar{ @@ -52977,6 +53011,7 @@ /obj/structure/cable{ icon_state = "0-8" }, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/starboard) "cNT" = ( @@ -53098,7 +53133,7 @@ dir = 4 }, /obj/machinery/door/airlock/external{ - req_access_txt = "13" + req_access_txt = "13;8;12" }, /turf/open/floor/plating, /area/maintenance/starboard/aft) @@ -53107,7 +53142,7 @@ dir = 8 }, /obj/machinery/door/airlock/external{ - req_access_txt = "13" + req_access_txt = "13;8;12" }, /turf/open/floor/plating, /area/maintenance/starboard/aft) @@ -53541,6 +53576,7 @@ /obj/structure/sign/poster/official/safety_internals{ pixel_x = -32 }, +/obj/machinery/space_heater, /turf/open/floor/plasteel/white, /area/science/xenobiology) "cTZ" = ( @@ -53709,6 +53745,13 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/aft) +"dkV" = ( +/obj/machinery/space_heater, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "dly" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -53841,6 +53884,11 @@ }, /turf/open/floor/engine, /area/engine/engineering) +"dDV" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/space_heater, +/turf/open/floor/plasteel, +/area/quartermaster/warehouse) "dFX" = ( /turf/closed/wall, /area/crew_quarters/fitness/pool) @@ -53966,12 +54014,8 @@ }, /area/crew_quarters/fitness/pool) "ecE" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1; - name = "Mix to Waste" +/obj/machinery/atmospherics/pipe/simple/general/visible{ + dir = 5 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -54027,14 +54071,6 @@ }, /turf/open/floor/engine, /area/engine/engineering) -"epC" = ( -/obj/machinery/door/airlock{ - desc = "To keep the station within regulations, space IKEA requires one storage cupboard for their Nanotrasen partnership to continue."; - id_tag = "MaintDorm1"; - name = "Furniture Storage" - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) "epD" = ( /obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden, /obj/machinery/light{ @@ -54121,6 +54157,10 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/port) +"eyr" = ( +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/maintenance/fore) "eyM" = ( /obj/machinery/mineral/ore_redemption{ input_dir = 2; @@ -54629,6 +54669,11 @@ /obj/effect/turf_decal/stripes/corner, /turf/open/floor/plasteel, /area/hydroponics) +"fzU" = ( +/obj/effect/turf_decal/stripes/line, +/obj/machinery/space_heater, +/turf/open/floor/plasteel, +/area/hallway/secondary/entry) "fAj" = ( /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ @@ -54723,6 +54768,11 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/plasteel, /area/science/circuit) +"fKv" = ( +/obj/machinery/portable_atmospherics/scrubber/huge, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plasteel, +/area/engine/atmos) "fMp" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/dark, @@ -54886,10 +54936,6 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/fore) -"gfr" = ( -/obj/structure/bed, -/turf/open/floor/plating, -/area/maintenance/port) "gfC" = ( /obj/effect/turf_decal/tile/red, /obj/structure/chair{ @@ -54904,13 +54950,9 @@ /turf/open/floor/carpet, /area/crew_quarters/cryopod) "gfJ" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ +/obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 4 }, -/obj/machinery/door/airlock/atmos{ - name = "Atmospherics"; - req_access_txt = "24" - }, /turf/open/floor/plasteel, /area/engine/atmos) "ghD" = ( @@ -54947,11 +54989,12 @@ dir = 4 }, /obj/structure/closet/secure_closet/atmospherics, -/obj/item/cartridge/atmos, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/turf/open/floor/plasteel/dark/corner{ dir = 1 }, -/turf/open/floor/plasteel, /area/engine/atmos) "gnf" = ( /obj/structure/disposalpipe/segment{ @@ -55106,6 +55149,7 @@ /obj/item/radio/intercom{ pixel_y = 20 }, +/obj/machinery/space_heater, /turf/open/floor/plasteel, /area/security/processing) "gGH" = ( @@ -55191,17 +55235,28 @@ /area/crew_quarters/fitness) "gQX" = ( /obj/machinery/button/door{ - desc = "Alright, GAMER! Want to take your PWRGAME addiction to the MAX? Just smash this button with your chubby chetto encrusted hands an- oh, you broke the switch. Good job, idiot."; - id = "RIPFUN"; - name = "Powerful Gamer Toggle"; + id = "LockerShitter4"; + name = "Door Bolt Control"; normaldoorcontrol = 1; - pixel_x = -24; - pixel_y = 7; + pixel_x = 14; + pixel_y = 38; specialfunctions = 4 }, -/obj/structure/table_frame/wood, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/structure/toilet/secret/low_loot{ + dir = 4 + }, +/obj/structure/sink{ + dir = 1; + pixel_y = 25 + }, +/obj/structure/mirror{ + pixel_y = 32 + }, +/obj/machinery/light/small{ + dir = 8 + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "gRZ" = ( /obj/structure/bookcase{ name = "Forbidden Knowledge" @@ -55271,16 +55326,6 @@ /obj/effect/turf_decal/tile/blue, /turf/open/floor/plasteel, /area/crew_quarters/fitness) -"hew" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/turf/open/floor/plating, -/area/maintenance/port) "hgO" = ( /obj/structure/table, /obj/item/storage/pill_bottle/dice{ @@ -55327,10 +55372,6 @@ }, /turf/closed/wall, /area/crew_quarters/dorms) -"hnl" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, -/turf/closed/wall, -/area/maintenance/port) "hnU" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -55449,13 +55490,19 @@ }, /turf/open/floor/engine, /area/engine/engineering) +"hOd" = ( +/obj/machinery/portable_atmospherics/scrubber, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "hOv" = ( /obj/structure/table/wood/fancy, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 4; - pixel_y = 5 - }, /obj/item/reagent_containers/food/snacks/burger/plain, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, /turf/open/floor/wood, /area/crew_quarters/bar) "hOI" = ( @@ -55472,21 +55519,21 @@ /turf/open/floor/engine, /area/engine/engineering) "hPs" = ( -/obj/structure/fireplace{ - pixel_y = -6 - }, /obj/machinery/airalarm{ dir = 8; pixel_x = 23 }, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "hPP" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 8 }, /turf/closed/wall, /area/quartermaster/warehouse) @@ -55541,6 +55588,10 @@ }, /turf/open/floor/wood, /area/crew_quarters/bar) +"hUv" = ( +/obj/machinery/space_heater, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) "hVs" = ( /turf/open/floor/plasteel/dark, /area/engine/engineering) @@ -55642,6 +55693,7 @@ /turf/open/floor/plasteel, /area/crew_quarters/fitness/pool) "ipA" = ( +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/department/medical/morgue) "itD" = ( @@ -55693,13 +55745,6 @@ /obj/effect/turf_decal/tile/green, /turf/open/floor/plasteel, /area/hallway/primary/starboard) -"iwB" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/closed/wall, -/area/maintenance/port) "izg" = ( /obj/item/cigbutt/cigarbutt, /turf/open/floor/plating, @@ -55858,9 +55903,17 @@ /turf/open/floor/plasteel, /area/engine/engineering) "iYC" = ( -/obj/effect/spawner/structure/window, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plasteel, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/machinery/door/firedoor/heavy, +/obj/machinery/door/airlock/atmos{ + name = "Atmospherics"; + req_access_txt = "24" + }, +/turf/open/floor/plasteel/dark/corner{ + dir = 1 + }, /area/engine/atmos) "iYE" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -56036,12 +56089,16 @@ /turf/open/floor/plasteel, /area/crew_quarters/fitness) "jxF" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/yellow{ + dir = 1 }, -/obj/structure/reagent_dispensers/fueltank, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/machinery/space_heater, +/turf/open/floor/plasteel, +/area/construction/mining/aux_base) "jyO" = ( /obj/effect/turf_decal/tile/red{ dir = 1 @@ -56180,6 +56237,37 @@ }, /turf/open/floor/plating, /area/maintenance/fore/secondary) +"jLl" = ( +/obj/structure/rack, +/obj/item/pickaxe{ + pixel_x = 5 + }, +/obj/item/shovel{ + pixel_x = -5 + }, +/obj/item/shovel{ + pixel_x = -5 + }, +/obj/item/shovel{ + pixel_x = -5 + }, +/obj/item/pickaxe{ + pixel_x = 5 + }, +/obj/item/pickaxe{ + pixel_x = 5 + }, +/obj/item/storage/bag/ore/large, +/obj/item/storage/bag/ore/large, +/obj/item/storage/bag/ore/large, +/obj/item/clothing/suit/hooded/wintercoat/aformal, +/obj/item/clothing/suit/hooded/wintercoat/aformal, +/obj/item/clothing/suit/hooded/wintercoat/aformal, +/obj/item/clothing/shoes/winterboots, +/obj/item/clothing/shoes/winterboots, +/obj/item/clothing/shoes/winterboots, +/turf/open/floor/plasteel, +/area/hallway/secondary/entry) "jLn" = ( /obj/machinery/door/airlock/engineering{ name = "Gravity Generator"; @@ -56358,8 +56446,19 @@ }, /turf/open/floor/plating, /area/maintenance/fore/secondary) +"khU" = ( +/obj/machinery/atmospherics/components/binary/pump{ + dir = 4; + name = "N2 to Pure" + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "khV" = ( /obj/machinery/vending/cola/red, +/obj/structure/sign/poster/contraband/robust_softdrinks{ + pixel_x = -32; + pixel_y = 32 + }, /turf/open/floor/plasteel/dark, /area/hallway/primary/central) "kjm" = ( @@ -56451,6 +56550,13 @@ }, /turf/open/floor/plasteel, /area/security/range) +"kvI" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/maintenance/aft) "kvL" = ( /obj/structure/cable{ icon_state = "1-2" @@ -56661,10 +56767,6 @@ }, /turf/open/floor/plasteel, /area/security/brig) -"kQO" = ( -/obj/structure/reagent_dispensers/keg/semen, -/turf/open/floor/plating, -/area/maintenance/bar) "kSb" = ( /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, @@ -56709,6 +56811,10 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/starboard) +"kYy" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "kZE" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -56745,6 +56851,15 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel, /area/security/range) +"lcu" = ( +/obj/effect/spawner/lootdrop/maintenance, +/obj/structure/reagent_dispensers/fueltank, +/turf/open/floor/plating, +/area/maintenance/port) +"lfj" = ( +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/maintenance/disposal) "lfB" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ dir = 4 @@ -56834,7 +56949,7 @@ /turf/open/floor/engine, /area/engine/engineering) "lsk" = ( -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/kink, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "ltK" = ( @@ -57255,6 +57370,12 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/fore) +"mCy" = ( +/obj/machinery/space_heater{ + anchored = 1 + }, +/turf/open/floor/plasteel/dark, +/area/engine/engineering) "mDB" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -57635,6 +57756,13 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/locker) +"nNP" = ( +/obj/machinery/atmospherics/components/binary/pump{ + dir = 4; + name = "O2 to Pure" + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "nQi" = ( /obj/machinery/recharge_station, /turf/open/floor/plating, @@ -57673,6 +57801,10 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/dorms) +"nTd" = ( +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/ai_monitored/turret_protected/aisat/hallway) "nTG" = ( /obj/structure/chair{ dir = 1 @@ -57747,8 +57879,7 @@ pixel_y = 20 }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 4; - pixel_y = 5 + dir = 4 }, /turf/open/floor/wood, /area/crew_quarters/bar) @@ -57858,17 +57989,26 @@ /turf/open/floor/plasteel, /area/security/prison) "omY" = ( -/obj/item/flashlight/lamp/green{ - pixel_x = -2; - pixel_y = 15 +/obj/machinery/button/door{ + id = "LockerShitter4"; + name = "Door Bolt Control"; + normaldoorcontrol = 1; + pixel_x = 14; + pixel_y = 38; + specialfunctions = 4 }, -/obj/structure/dresser{ - desc = "There's plenty of clothes here to change into! It has a surprising amount of variety, too."; - name = "Dresser"; - pixel_y = 7 +/obj/structure/toilet/secret/low_loot{ + dir = 4 }, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/structure/sink{ + dir = 1; + pixel_y = 25 + }, +/obj/machinery/light/small{ + dir = 8 + }, +/turf/open/floor/mineral/titanium/blue, +/area/crew_quarters/toilet/locker) "oqj" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -58023,10 +58163,18 @@ }, /turf/open/floor/engine, /area/engine/engineering) +"oEr" = ( +/obj/machinery/space_heater, +/turf/open/floor/plasteel, +/area/engine/engineering) "oEZ" = ( /obj/effect/spawner/lootdrop/keg, /turf/open/floor/plating, /area/maintenance/starboard/aft) +"oFT" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/closed/wall, +/area/storage/art) "oHB" = ( /turf/open/floor/plasteel/dark, /area/crew_quarters/dorms) @@ -58066,6 +58214,15 @@ }, /turf/open/floor/plating, /area/crew_quarters/abandoned_gambling_den) +"oMH" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, +/obj/machinery/space_heater{ + anchored = 1 + }, +/turf/open/floor/engine, +/area/engine/engineering) "oNz" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 8 @@ -58159,12 +58316,7 @@ "oZl" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/closet/wardrobe/pjs, -/obj/item/clothing/under/costume/maid, -/obj/item/clothing/under/costume/maid, /obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/under/rank/civilian/janitor/maid, -/obj/item/clothing/accessory/maidapron, -/obj/item/clothing/accessory/maidapron, /obj/machinery/light{ dir = 8 }, @@ -58176,6 +58328,11 @@ }, /turf/open/floor/engine, /area/engine/engineering) +"pck" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/maintenance/aft) "pem" = ( /obj/machinery/button/door{ desc = "Bolts the doors to the Private Study."; @@ -58225,6 +58382,13 @@ }, /turf/open/floor/wood, /area/crew_quarters/bar) +"plL" = ( +/obj/machinery/portable_atmospherics/pump, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "plS" = ( /obj/machinery/door/window/brigdoor/security/cell{ id = "Cell 1"; @@ -58273,7 +58437,6 @@ /turf/open/floor/wood, /area/crew_quarters/bar) "pqs" = ( -/obj/machinery/vending/clothing, /obj/structure/disposalpipe/segment{ dir = 4 }, @@ -58540,6 +58703,13 @@ }, /turf/open/floor/plasteel, /area/security/processing) +"pZr" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/maintenance/aft) "qaY" = ( /obj/structure/table/reinforced, /obj/effect/turf_decal/tile/bar, @@ -58787,17 +58957,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plasteel/dark, /area/engine/engineering) -"rca" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 4 - }, -/obj/structure/closet/secure_closet/atmospherics, -/obj/item/cartridge/atmos, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "rcD" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -58841,11 +59000,11 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/machinery/vending/kink, /obj/machinery/light{ dir = 4; light_color = "#e8eaff" }, +/obj/machinery/vending/games, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "rfW" = ( @@ -58869,6 +59028,10 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel, /area/security/processing) +"rjG" = ( +/obj/machinery/space_heater, +/turf/open/floor/plasteel, +/area/quartermaster/miningdock) "rjH" = ( /obj/structure/cable{ icon_state = "2-4" @@ -58964,11 +59127,6 @@ dir = 4 }, /obj/structure/closet/wardrobe/black, -/obj/item/clothing/under/dress/skirt, -/obj/item/clothing/head/beret/black, -/obj/item/clothing/head/beret/black, -/obj/item/clothing/under/custom/trendy_fit, -/obj/item/clothing/under/custom/trendy_fit, /obj/item/clothing/under/dress/sundress, /turf/open/floor/plasteel, /area/crew_quarters/fitness) @@ -58984,6 +59142,13 @@ }, /turf/open/floor/plasteel, /area/engine/gravity_generator) +"rto" = ( +/obj/machinery/portable_atmospherics/scrubber, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "rtC" = ( /obj/effect/decal/cleanable/blood/old, /turf/open/floor/plating, @@ -59302,6 +59467,12 @@ /obj/effect/spawner/lootdrop/maintenance, /turf/open/floor/plating, /area/maintenance/fore) +"siv" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 9 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "slk" = ( /obj/machinery/door/airlock/maintenance{ req_access_txt = "12" @@ -59568,6 +59739,10 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) +"sKd" = ( +/obj/machinery/status_display/evac, +/turf/closed/wall, +/area/hallway/primary/central) "sLa" = ( /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ @@ -59652,6 +59827,15 @@ }, /turf/open/floor/plasteel, /area/quartermaster/office) +"sRO" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/door/airlock/maintenance{ + req_one_access_txt = "8;12" + }, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "sRT" = ( /obj/machinery/vending/cola/random, /turf/open/floor/wood, @@ -59678,6 +59862,13 @@ }, /turf/open/floor/plasteel/dark, /area/engine/engineering) +"sTP" = ( +/obj/machinery/light/small{ + dir = 8 + }, +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/maintenance/port/aft) "sUh" = ( /obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/closed/wall, @@ -59723,9 +59914,16 @@ /turf/open/floor/plating, /area/maintenance/fore/secondary) "sXA" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/closed/wall, /area/maintenance/bar) +"sXM" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/maintenance/aft) "sXV" = ( /turf/closed/wall/r_wall, /area/security/range) @@ -59784,6 +59982,10 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/wood, /area/crew_quarters/bar) +"tiF" = ( +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/maintenance/aft) "tkq" = ( /obj/structure/cable{ icon_state = "4-8" @@ -59868,11 +60070,6 @@ }, /turf/open/floor/plasteel/dark, /area/engine/engineering) -"txm" = ( -/obj/structure/table/wood/fancy/royalblue, -/obj/item/crowbar/red, -/turf/open/floor/plating, -/area/maintenance/port) "tyX" = ( /obj/structure/cable{ icon_state = "4-8" @@ -60499,11 +60696,10 @@ /turf/closed/wall/r_wall, /area/maintenance/disposal/incinerator) "uQS" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 1; - pixel_x = 5 - }, /obj/machinery/light/small, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 1 + }, /turf/open/floor/mineral/titanium/blue, /area/crew_quarters/toilet) "uRd" = ( @@ -60564,6 +60760,13 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/aft) +"uWy" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 + }, +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "uXt" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden, /turf/open/floor/plasteel, @@ -60694,6 +60897,10 @@ }, /turf/open/floor/wood, /area/maintenance/bar) +"vke" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/locker) "vmQ" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 10 @@ -60760,6 +60967,15 @@ /obj/structure/cable, /turf/open/floor/carpet, /area/crew_quarters/cryopod) +"vsQ" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/structure/closet/emcloset, +/turf/open/floor/plasteel/white/corner{ + dir = 1 + }, +/area/hallway/secondary/entry) "vsT" = ( /obj/structure/closet/crate, /obj/item/book/manual/wiki/telescience, @@ -61095,6 +61311,10 @@ }, /turf/open/floor/engine, /area/engine/engineering) +"vUI" = ( +/obj/machinery/status_display/evac, +/turf/closed/wall, +/area/ai_monitored/storage/eva) "vZA" = ( /obj/structure/cable, /turf/open/floor/plating/snowed/smoothed/icemoon, @@ -61136,6 +61356,11 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) +"wcr" = ( +/obj/machinery/portable_atmospherics/pump, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plasteel, +/area/engine/atmos) "wcB" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 10 @@ -61173,6 +61398,10 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/fitness/pool) +"wiI" = ( +/obj/machinery/space_heater, +/turf/open/floor/wood, +/area/security/vacantoffice) "wje" = ( /obj/structure/rack, /obj/item/instrument/banjo, @@ -61221,6 +61450,10 @@ }, /turf/open/floor/plating, /area/construction/mining/aux_base) +"wpr" = ( +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/maintenance/port) "wql" = ( /obj/structure/extinguisher_cabinet, /turf/closed/wall/r_wall, @@ -61281,7 +61514,7 @@ /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/yellow/visible, +/obj/machinery/atmospherics/pipe/layer_manifold, /turf/open/floor/plating, /area/engine/atmos) "wAh" = ( @@ -61315,6 +61548,14 @@ }, /turf/closed/wall/r_wall, /area/maintenance/disposal/incinerator) +"wHR" = ( +/obj/machinery/light, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/machinery/space_heater, +/turf/open/floor/plasteel/white/corner, +/area/hallway/secondary/entry) "wHT" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /turf/open/floor/plating, @@ -61325,6 +61566,10 @@ }, /turf/open/floor/plasteel/dark, /area/engine/engineering) +"wJF" = ( +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/storage/tech) "wKe" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ @@ -61717,6 +61962,12 @@ /obj/item/radio/headset/headset_cargo, /turf/open/floor/plasteel, /area/quartermaster/storage) +"xBF" = ( +/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "xDM" = ( /obj/machinery/camera{ c_tag = "Locker Room South"; @@ -61922,10 +62173,18 @@ }, /turf/open/floor/plating, /area/security/processing) +"xXg" = ( +/obj/machinery/space_heater, +/turf/open/floor/plasteel, +/area/quartermaster/warehouse) "xXi" = ( /obj/machinery/vending/clothing, /turf/open/floor/plasteel, /area/crew_quarters/fitness) +"xZo" = ( +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/construction) "xZD" = ( /obj/structure/closet/lasertag/red, /obj/item/clothing/under/misc/pj/red, @@ -62008,6 +62267,11 @@ /obj/item/folder/blue, /turf/open/floor/plasteel/dark, /area/hallway/primary/central) +"yjo" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/maintenance/starboard) "ykN" = ( /obj/machinery/atmospherics/pipe/heat_exchanging/simple, /turf/open/floor/plating/snowed/smoothed/icemoon, @@ -68797,11 +69061,11 @@ aBM aBM aBM aBM -aBM -aBM -aBM -aBM -aBM +crk +crk +crk +crk +crk aBM aBM aBM @@ -69054,6 +69318,11 @@ aBM aBM aBM aBM +crk +crk +crk +crk +crk aBM aBM aBM @@ -69063,16 +69332,11 @@ aBM aBM aBM aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM +crk +crk +crk +crk +crk aBM aBM aBM @@ -69311,9 +69575,11 @@ aBM aBM aBM aBM -aBM -aBM +crk +crk aud +crk +crk aBM aBM aBM @@ -69323,13 +69589,11 @@ aBM aBM aBM aBM -aBM -aBM -aBM -aBM +crk +crk auC -aBM -aBM +crk +crk aBM aBM aBM @@ -69568,6 +69832,11 @@ aBM aBM aBM aBM +crk +crk +crk +crk +crk aBM aBM aBM @@ -69577,16 +69846,11 @@ aBM aBM aBM aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM +crk +crk +crk +crk +crk aBM aBM aBM @@ -69825,6 +70089,11 @@ aBM aBM aBM aBM +crk +crk +crk +crk +crk aBM aBM aBM @@ -69834,16 +70103,11 @@ aBM aBM aBM aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM +crk +crk +crk +crk +crk aBM aBM aBM @@ -70082,6 +70346,11 @@ aBM aBM aBM aBM +crk +crk +crk +crk +crk aBM aBM aBM @@ -70091,16 +70360,11 @@ aBM aBM aBM aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM +crk +crk +crk +crk +crk aBM aBM aBM @@ -70339,11 +70603,11 @@ aBM aBM aBM aBM -aBM +crk crk auj crk -aBM +crk aBM aBM crk @@ -70353,11 +70617,11 @@ crk crk aBM aBM -aBM +crk crk auj crk -aBM +crk aBM aBM aBM @@ -71384,7 +71648,7 @@ awW awW awW aQG -aRX +wHR arB aBM aBM @@ -71392,7 +71656,7 @@ aBM aBM aBM arB -awZ +vsQ ayk awW aAD @@ -72421,9 +72685,9 @@ aBM aBM awW awZ +jHh ayl -ayl -aAE +jLl awW aBM aBM @@ -72678,7 +72942,7 @@ aBM aBM awW awZ -ayl +jHh ayl bgi awW @@ -73678,7 +73942,7 @@ atI atI arE ayq -ayq +jxF auc avp axI @@ -74475,7 +74739,7 @@ azz ayl azz aPu -ayl +aNh aIK ayl beM @@ -74732,10 +74996,10 @@ ayl ayl aWc baG -ayl +aNh aIK ayl -beM +fzU arB aBM aBM @@ -76016,7 +76280,7 @@ aUO aUO aXL aXZ -aUO +wiI czK bbe beO @@ -76025,7 +76289,7 @@ bgj bgj bjc cAF -cAF +lfj bja wWu wWu @@ -76758,7 +77022,7 @@ ayF ayF alU aoT -amC +atJ aqO arG asc @@ -77554,7 +77818,7 @@ aPz aPz aPz aPz -aSg +wpr aWj aXP aZr @@ -77568,14 +77832,14 @@ bfh aPz aPz aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF aBM aBM aBM @@ -77824,17 +78088,17 @@ bea bfq bji bkF -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF aBM aBM aBM @@ -78081,17 +78345,17 @@ bdZ bhO bjh bkE -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF aBM aBM aBM @@ -78331,25 +78595,25 @@ aXQ aXQ aXQ aXQ -aPz -aPz -epC -aPz +aXQ +aXQ +aXQ +aXQ bhQ bjj bkF -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF aBM aBM aBM @@ -78588,25 +78852,25 @@ aXQ aZt aXQ ycd -aPz +aXQ omY -cMS +aXQ gQX bhQ bjj bkF -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF aBM aBM aBM @@ -78845,25 +79109,25 @@ aXQ aZv aXQ bbL -aPz +aXQ bdJ -txm +aXQ bgr -iwB -hew +bhQ +bjj bkF -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF aBM aBM aBM @@ -79102,25 +79366,25 @@ aWy aYe bbq aZw -aPz +kYy bct bfa -gfr +bfa bhQ bjk bkE -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM -aBM +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF +ayF aBM aBM aBM @@ -79356,27 +79620,27 @@ aSV aUo aUX aXp +vke baO -aZo baw -aPz +baO hPs cBn -bgs -hnl +bfa +bhQ bjk bkF -aBM -aBM -aBM -aBM -aBM -aBM +ayF +ayF +ayF +ayF +ayF +ayF avd -aBM -aBM -aBM -aBM +ayF +ayF +ayF +ayF aBM aBM aBM @@ -79616,15 +79880,15 @@ aXQ aXQ aXQ aXQ -aPz -aPz -aPz -aPz +aXQ +aXQ +aXQ +aXQ bhQ bjk aPz -aBM -aBM +ayF +ayF boI bqi brJ @@ -79632,8 +79896,8 @@ boI brJ bvS boI -aBM -aBM +ayF +ayF aBM aBM aBM @@ -79880,8 +80144,8 @@ bgt bhS bjk aPz -aBM -aBM +ayF +ayF blW bqj brK @@ -79889,9 +80153,9 @@ blW brK bvT blW -aBM -aBM -aBM +ayF +ayF +ayF aBM aBM aBM @@ -80133,7 +80397,7 @@ aQN cBh bdL aPA -bgt +lcu bhR bjk aZE @@ -80142,14 +80406,14 @@ blW blW bqi cyD -blW +aZE cyD bvS blW -aBM -aBM -aBM -aBM +ayF +ayF +ayF +ayF aBM aBM ayF @@ -80355,7 +80619,7 @@ alU amE ann amC -amC +atJ alU amC alU @@ -80403,11 +80667,11 @@ btr bnw bvV blW -aBM -aBM -aBM -aBM -aBM +ayF +ayF +ayF +ayF +ayF ayF ayF ayF @@ -80662,8 +80926,8 @@ bvU aZE ayF ayF -aBM -aBM +ayF +ayF ayF ayF ayF @@ -80917,10 +81181,10 @@ bjt biq bvV blW -aBM -aBM -aBM -aBM +ayF +ayF +ayF +ayF ayF ayF ayF @@ -81174,10 +81438,10 @@ bjr buC bvV blW -aBM -aBM -aBM -aBM +ayF +ayF +ayF +ayF ayF ayF bxy @@ -81431,10 +81695,10 @@ bjr bkt bvV blW -aBM -aBM -aBM -aBM +ayF +ayF +ayF +ayF ayF ayF bxy @@ -81688,10 +81952,10 @@ bjr bjr bvV bxu -aBM -aBM -aBM -aBM +ayF +ayF +ayF +ayF ayF ayF bxy @@ -81931,7 +82195,7 @@ aQW aQW xDM aPA -jxF +aWv aYb aZE bjp @@ -82694,7 +82958,7 @@ aPF aQZ aRa aTF -aPG +oFT aSX hPP aZF @@ -82751,7 +83015,7 @@ cAh chT bHE bHE -ckv +sTP bHE bCq bLv @@ -82954,7 +83218,7 @@ aPJ aPJ aVC aXJ -bgA +dDV aZp baY bcJ @@ -83773,7 +84037,7 @@ mrR dKP odx rBq -kQO +evR bCq bUs bLv @@ -83982,9 +84246,9 @@ aTJ aPK aWA aWC -baS +xXg aZI -baS +xXg cCn bdS bdU @@ -84010,7 +84274,7 @@ bEK byE byE avl -byE +rjG bGi ayF ayF @@ -84786,7 +85050,7 @@ bxy crk crk bCq -bHE +ceW bRh bLu bCq @@ -85808,7 +86072,7 @@ bAo bTE bGo bHC -bHE +ceW bCq bCq bLv @@ -86015,7 +86279,7 @@ arl arP asS sfs -aqR +eyr awb axt ayG @@ -86346,7 +86610,7 @@ bLw bLw caq cbw -bHE +ceW ciT bCq bSs @@ -88412,7 +88676,7 @@ ccw cnZ coH cgR -cgR +oEr cig nEI ccw @@ -88896,7 +89160,7 @@ bJj bKu bLy bCs -bNJ +xZo bNJ bKx cjL @@ -89111,7 +89375,7 @@ ayL ayW ayW ayW -ayW +vUI aJq aJq aOE @@ -89153,7 +89417,7 @@ bFa bFa bFa bCs -bNJ +xZo bNJ apV cjL @@ -89192,7 +89456,7 @@ hOI qmG uqX oEe -tcF +oMH uSL fft ccw @@ -89455,7 +89719,7 @@ vOF fAX hVs iWD -hVs +hUv fPM ccw ayF @@ -90173,7 +90437,7 @@ aXf aJq bBi bCs -bFa +wJF bFa bFa bET @@ -91685,7 +91949,7 @@ aKF aMf aNB aOE -aPW +aPS aRr aSD ceh @@ -91990,7 +92254,7 @@ bUF bVN bWN bXM -bYJ +bLK bRi bZy cbu @@ -92240,14 +92504,14 @@ alk bNQ bOV bQk -bRt +bVQ bSD bTM bUH bVQ bVZ bXM -bLK +iYC cew bTh cdt @@ -92496,13 +92760,13 @@ bLL bOd bNQ bOU -bTO -bRr -bSE +bQj +bOd +bMK bTN -gfJ -bVP -bWP +bTP +bRy +cfN bXL bLK bRj @@ -92539,7 +92803,7 @@ ccw dSF vLM sAQ -hVs +hUv gAE ccw ayF @@ -92709,7 +92973,7 @@ gfD woR dgz aJw -aJw +sKd aMh aJq aOE @@ -92755,7 +93019,7 @@ bNS bOX bQm bRv -cGG +bRs glY bTP bVX @@ -93012,8 +93276,8 @@ bNR bOW bQl bRu -iYC -rca +bRs +glY bUI bVR bWQ @@ -93268,7 +93532,7 @@ bMK bMK bOY bQn -bRx +bRs bMK bUP bUJ @@ -93523,7 +93787,7 @@ bKz bLK bQr bNT -bOV +bQu bQo bRw bSF @@ -93560,8 +93824,8 @@ jIb qXZ dVX dVX -hVs -hVs +mCy +mCy ccw ayF ayF @@ -94036,7 +94300,7 @@ bJv bKB bLK bMM -bNV +bOd bOQ bQj bRy @@ -94305,12 +94569,12 @@ bVV bVV bWT bZG -caE -cbA -ccy -bZH -bZI -bQu +bOd +bOd +bOd +bOd +bOd +bOd bOd cgW cit @@ -94553,19 +94817,19 @@ bMO bIF bOZ bQp -bRA -bTP -bOd +bRx +bTO +bTR bOd bOd bOd bOd bXS bOd -bXU -cbA -ccy -bZH +bOd +bOd +bOd +bOd bZI cfi bOd @@ -94809,10 +95073,10 @@ bLK bMR bIH bJF -bRy -bTQ -ecE -bOd +bRt +bRA +bTP +bVP bOd bOd bOd @@ -94823,8 +95087,8 @@ bOd bOd bOd bOd -bOd -bOd +dkV +fKv cfQ cgY ciu @@ -95066,11 +95330,11 @@ bLK bMQ bNY bPa -bYN +bMQ bRC bSK -bOd -bOd +bWP +bZH bOd bOd bOd @@ -95080,8 +95344,8 @@ bOd bOd bOd bOd -bOd -bOd +rto +wcr apa cgX apF @@ -95326,8 +95590,8 @@ bPd cBF bRD bSK -bOd -bOd +bWP +bZH bOd bOd bOd @@ -95337,9 +95601,9 @@ bOd bOd cBJ bOd -bOd -bOd -bOd +hOd +plL +bTP cha civ axs @@ -95581,10 +95845,10 @@ bMS cfQ bPc bQs -bTR +cez bSJ -bOd -bOd +bWP +bZH bOd bOd bOd @@ -95594,9 +95858,9 @@ bOd bOd bOd bOd -bOd -bOd -bOd +cfQ +cez +siv cgZ bSK crk @@ -95840,9 +96104,7 @@ bOR bQv bRF bSM -bTS -bOd -bOd +bXU bOd bOd bOd @@ -95853,6 +96115,8 @@ bOd bOd bOd bOd +bTP +cfQ cbD chb wzX @@ -96094,15 +96358,13 @@ bLK bMU bOc bPe -bTP +bMY bRE bUL -cfT -bOd -bOd -bOd -bOd -bOd +bYJ +caE +cGG +ecE bOd bOd bOd @@ -96110,6 +96372,8 @@ bOd bOd bOd bOd +khU +nNP cfP ccz bSJ @@ -96349,12 +96613,15 @@ bvd bKH bLK bMX -bTP +bMY bPg bQx -bRF -bSM +bSE +bTQ bTU +cbA +bOd +gfJ bOd bOd bOd @@ -96362,10 +96629,7 @@ bOd bOd bOd bOd -bOd -bOd -bMZ -bTS +xBF caH cbE chd @@ -96611,8 +96875,8 @@ bPf bQw bRG bSN -bPg -bTS +bYN +ccy bTS cCE bWa @@ -96621,7 +96885,7 @@ bTS bTS bYL bTS -cdB +bTS caF cbB cfT @@ -96795,7 +97059,7 @@ uhm ahn aiA ahn -grc +bMs anE aod ahn @@ -97119,14 +97383,14 @@ bvj bvd bKH bLK -bMY +bLK bOf bPh bQy bRI ceA bPh -bQy +cdB bRI cCF bPh @@ -99240,7 +99504,7 @@ cvk cvX cvX cvX -cvX +nTd cwq cwq cva @@ -99443,12 +99707,12 @@ bUY pRg bWe pRg -bWe +kvI bWe cdE bAw bzs -bAw +tiF caK cfj ciB @@ -99688,7 +99952,7 @@ bFA bIm bJD bKK -bLS +pck bNc bOj bNc @@ -100212,7 +100476,7 @@ bMa bTZ bKH bzs -bAw +tiF bXZ bAw bZN @@ -101947,8 +102211,8 @@ crk alO arp alO -anf -anf +aBF +aBF anf anf anf @@ -102543,7 +102807,7 @@ ceJ cAe cmj cne -bHd +sXM bPn ayF ayF @@ -103028,7 +103292,7 @@ bFH bHb bIw bBN -bKT +pZr bMb bNd bOt @@ -103309,7 +103573,7 @@ cfq bKT bAw ciH -bHd +sXM bzs bAw cmk @@ -103488,8 +103752,8 @@ aoO apB aqx art -anf -anf +aBF +aBF auF alP awH @@ -103534,7 +103798,7 @@ bon buG bvA bon -bAw +tiF bzg bLS bLS @@ -104012,7 +104276,7 @@ alP alP alP alP -ayf +uWy aFm aGF aIq @@ -105542,7 +105806,7 @@ ayF ayF ayF alO -anf +aBF anf asy anf @@ -106569,7 +106833,7 @@ aBM ayF ayF alO -anf +aBF anf arw nuw @@ -108683,9 +108947,9 @@ bEz bFS bJT bLh -bMs -bMs -bMs +bvx +bvx +bvx bPN bQS bSf @@ -110762,7 +111026,7 @@ lZl cNW chC ciL -cOe +cou cOe clv cQw @@ -110974,8 +111238,8 @@ aTm aTm bgd bhG -bhG -bhG +yjo +yjo blO bmc bnq @@ -111230,8 +111494,8 @@ bcC cBl aPq bgg -aNa -ayF +aMZ +bky bky bqh bme @@ -112556,7 +112820,7 @@ cNW cNW cNW cNW -clt +sRO cNW cNW cNW @@ -113067,13 +113331,13 @@ kAJ clt cac cbh -cNW +cou ccV cOe clt cfv cBL -cOe +cou cNW ayF ayF @@ -113828,16 +114092,16 @@ ayF ayF ayF ayF -aBM -aBM +crk +crk ayF -aBM -aBM +crk +crk ayF ayF ayF -aBM -aBM +crk +crk ayF ayF cNW @@ -114076,8 +114340,8 @@ bky bky ayF aBM -aBM -aBM +crk +crk crk crk crk @@ -114336,7 +114600,7 @@ aBM aBM aBM ayF -ayF +crk ayF ayF ayF @@ -114850,7 +115114,7 @@ aBM aBM aBM ayF -ayF +crk ayF aBM aBM @@ -115107,7 +115371,7 @@ aBM aBM aBM ayF -ayF +crk ayF aBM aBM @@ -115878,7 +116142,7 @@ aBM aBM aBM ayF -ayF +crk ayF aBM aBM @@ -116135,7 +116399,7 @@ aBM aBM aBM ayF -ayF +crk ayF aBM aBM @@ -116392,7 +116656,7 @@ aBM aBM aBM ayF -ayF +crk ayF aBM aBM @@ -116906,7 +117170,7 @@ aBM aBM aBM ayF -ayF +crk ayF aBM aBM @@ -117163,7 +117427,7 @@ aBM aBM aBM ayF -ayF +crk ayF aBM aBM @@ -117420,7 +117684,7 @@ aBM aBM aBM ayF -ayF +crk ayF aBM aBM @@ -117677,7 +117941,7 @@ aBM aBM aBM ayF -ayF +crk ayF aBM aBM @@ -117934,7 +118198,7 @@ aBM aBM aBM ayF -ayF +crk ayF aBM aBM @@ -118191,7 +118455,7 @@ aBM aBM aBM ayF -ayF +crk ayF aBM aBM @@ -118705,7 +118969,7 @@ aBM aBM aBM ayF -ayF +crk ayF aBM aBM @@ -118962,7 +119226,7 @@ aBM aBM aBM ayF -ayF +crk ayF aBM aBM diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm index a87ea077b3..1c3741c18e 100644 --- a/_maps/map_files/KiloStation/KiloStation.dmm +++ b/_maps/map_files/KiloStation/KiloStation.dmm @@ -29538,6 +29538,14 @@ /obj/machinery/light/small{ dir = 8 }, +/obj/machinery/computer/security/telescreen{ + desc = "Used for watching the test chamber."; + dir = 4; + layer = 4; + name = "Test Chamber Telescreen"; + network = list("toxins"); + pixel_x = -32 + }, /turf/open/floor/plasteel/dark, /area/science/mixing) "aVT" = ( @@ -30469,9 +30477,8 @@ dir = 4 }, /obj/machinery/light{ - dir = 4 + dir = 1 }, -/obj/machinery/computer/nanite_cloud_controller, /turf/open/floor/plasteel/dark, /area/science/research) "aXx" = ( @@ -30583,7 +30590,8 @@ name = "science camera"; network = list("ss13","rd") }, -/obj/machinery/computer/nanite_chamber_control, +/obj/structure/table/reinforced, +/obj/item/storage/bag/money, /turf/open/floor/plasteel/dark, /area/science/research) "aXG" = ( @@ -31251,8 +31259,6 @@ dir = 1 }, /obj/structure/table/reinforced, -/obj/item/nanite_scanner, -/obj/item/nanite_remote, /turf/open/floor/plasteel/dark, /area/science/research) "aYO" = ( @@ -33284,14 +33290,6 @@ /obj/structure/chair{ dir = 4 }, -/obj/machinery/computer/security/telescreen{ - desc = "Used for watching the test chamber."; - dir = 8; - layer = 4; - name = "Test Chamber Telescreen"; - network = list("toxins"); - pixel_x = 30 - }, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, @@ -33793,14 +33791,6 @@ pixel_x = 24; pixel_y = -24 }, -/obj/machinery/computer/security/telescreen{ - desc = "Used for watching the test chamber."; - dir = 8; - layer = 4; - name = "Test Chamber Telescreen"; - network = list("toxins"); - pixel_x = 30 - }, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, @@ -35128,7 +35118,6 @@ dir = 4 }, /obj/effect/landmark/event_spawn, -/obj/machinery/nanite_program_hub, /turf/open/floor/plasteel/dark, /area/science/research) "beE" = ( @@ -54029,7 +54018,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel/dark, /area/crew_quarters/locker) @@ -62906,6 +62895,11 @@ /obj/structure/extinguisher_cabinet{ pixel_x = 24 }, +/obj/machinery/button/electrochromatic{ + pixel_x = 38; + pixel_y = -5; + id = "!interrogation_room" + }, /turf/open/floor/plasteel, /area/security/warden) "bWO" = ( @@ -73512,7 +73506,7 @@ }, /mob/living/simple_animal/bot/cleanbot{ auto_patrol = 1; - name = "\imprper Cleaner Bot" + name = "\improper Cleaner Bot" }, /turf/open/floor/plasteel/showroomfloor, /area/security/prison) @@ -78316,7 +78310,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /obj/structure/noticeboard{ dir = 4; pixel_x = -27 @@ -84861,7 +84855,7 @@ /turf/open/floor/engine, /area/engine/engineering) "iLn" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/open/floor/wood, /area/maintenance/port/fore) "iMb" = ( @@ -85144,7 +85138,7 @@ dir = 8 }, /obj/effect/turf_decal/bot, -/obj/machinery/nanite_chamber, +/obj/machinery/rnd/bepis, /turf/open/floor/plasteel/dark, /area/science/research) "kSc" = ( @@ -85411,14 +85405,6 @@ initial_gas_mix = "o2=14;n2=23;TEMP=300" }, /area/hallway/secondary/entry) -"sfp" = ( -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/machinery/nanite_programmer, -/turf/open/floor/plasteel/dark, -/area/science/research) "swG" = ( /obj/item/reagent_containers/food/drinks/drinkingglass{ pixel_x = 4; @@ -85513,6 +85499,12 @@ "uRM" = ( /turf/open/floor/wood, /area/security/vacantoffice) +"vjT" = ( +/obj/effect/spawner/structure/window/reinforced/tinted/electrochromatic{ + electrochromatic_id = "!interrogation_room" + }, +/turf/open/floor/plating, +/area/security/warden) "vle" = ( /obj/structure/festivus, /turf/open/floor/wood, @@ -107879,7 +107871,7 @@ agX agX agX aef -acH +vjT aBH aef aef @@ -123517,7 +123509,7 @@ aZv aXw kRh aXI -sfp +aXI beD bbj aNF @@ -126371,7 +126363,7 @@ bki bhQ bkN bIG -bki +bhQ bMB blH bhQ diff --git a/_maps/map_files/LambdaStation/lambda.dmm b/_maps/map_files/LambdaStation/lambda.dmm index 5d9018f4cc..901824a5de 100644 --- a/_maps/map_files/LambdaStation/lambda.dmm +++ b/_maps/map_files/LambdaStation/lambda.dmm @@ -707,27 +707,11 @@ /turf/open/floor/plasteel, /area/science/mixing) "acc" = ( -/obj/machinery/computer/security/telescreen/toxins{ - layer = 4; - network = list("toxins"); - pixel_y = 30 - }, /obj/effect/turf_decal/stripes/line{ dir = 9 }, /turf/open/floor/plasteel, /area/science/mixing) -"acd" = ( -/obj/machinery/computer/security/telescreen/toxins{ - layer = 4; - network = list("toxins"); - pixel_y = 30 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/science/mixing) "ace" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -1183,6 +1167,10 @@ name = "Mass Driver Door"; req_access_txt = "7" }, +/obj/machinery/computer/security/telescreen/toxins{ + dir = 1; + pixel_y = -32 + }, /turf/open/floor/plasteel, /area/science/mixing) "adg" = ( @@ -23482,9 +23470,7 @@ dir = 8 }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3, -/obj/structure/closet/l3closet/scientist{ - pixel_x = -2 - }, +/obj/structure/closet/l3closet/scientist, /turf/open/floor/plasteel/white, /area/science/explab) "aQI" = ( @@ -38272,12 +38258,10 @@ /turf/open/floor/plasteel/white, /area/medical/chemistry) "btD" = ( -/obj/machinery/chem_dispenser{ - layer = 2.7 - }, /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 1 }, +/obj/machinery/chem_dispenser/apothecary, /turf/open/floor/plasteel/white, /area/medical/chemistry) "btE" = ( @@ -45021,7 +45005,7 @@ /turf/open/floor/wood, /area/maintenance/bar) "bGM" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/open/floor/wood, /area/maintenance/bar) "bGN" = ( @@ -47241,7 +47225,6 @@ /area/hydroponics/garden/abandoned) "bKT" = ( /obj/item/poster/random_contraband, -/turf/open/floor/plating, /turf/open/floor/plating{ icon_state = "platingdmg2" }, @@ -58598,7 +58581,7 @@ /turf/open/space, /area/space/nearstation) "cgJ" = ( -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /turf/open/floor/plating, /area/maintenance/aft) "cgK" = ( @@ -62158,7 +62141,6 @@ /obj/structure/cable{ icon_state = "0-4" }, -/turf/open/floor/plating, /turf/open/floor/plating{ icon_state = "platingdmg2" }, @@ -63619,7 +63601,6 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/turf/open/floor/plating, /turf/open/floor/plating{ icon_state = "platingdmg2" }, @@ -72658,7 +72639,7 @@ /turf/open/floor/plasteel/grimy, /area/bridge) "cIV" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /obj/machinery/status_display/evac{ pixel_y = 32 }, @@ -75970,7 +75951,6 @@ }, /area/maintenance/department/medical) "cPo" = ( -/turf/open/floor/plating, /turf/open/floor/plating{ icon_state = "platingdmg2" }, @@ -76073,7 +76053,6 @@ }, /area/maintenance/fore/secondary) "cPB" = ( -/turf/open/floor/plating, /turf/open/floor/plating{ icon_state = "platingdmg2" }, @@ -76098,17 +76077,10 @@ }, /area/maintenance/department/crew_quarters/dorms) "cPE" = ( -/turf/open/floor/plating, /turf/open/floor/plating{ icon_state = "platingdmg2" }, /area/maintenance/department/crew_quarters/dorms) -"cPF" = ( -/turf/open/floor/plating, -/turf/open/floor/plating{ - icon_state = "platingdmg2" - }, -/area/maintenance/aft) "cPG" = ( /obj/structure/cable{ icon_state = "4-8" @@ -81517,6 +81489,10 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/aft) +"sZf" = ( +/obj/machinery/rnd/bepis, +/turf/open/floor/engine, +/area/science/explab) "tbT" = ( /obj/machinery/power/emitter/anchored{ dir = 1; @@ -112996,7 +112972,7 @@ aAY aAY aAY abK -acd +ace acH ajC abJ @@ -113803,7 +113779,7 @@ aFb aFO aGD aHo -aGD +aHp aDr aaA aaA @@ -114059,7 +114035,7 @@ aEj aFc aFO aGD -aHp +aGD aGD aDr apk @@ -114572,9 +114548,9 @@ aJP aKA aFe aDr -aGD aHq aGD +sZf aDr aJI aKB @@ -115439,7 +115415,7 @@ cgm thv uRw boU -cPF +cfm chI cqg cWW @@ -118541,7 +118517,7 @@ aaA ceG cqt bYa -cPF +cfm ceG aaA aaA @@ -119299,7 +119275,7 @@ cQK bYa bYa cRQ -cPF +cfm chI cRv bYa @@ -134623,7 +134599,7 @@ aab aab aJw aKk -aKk +aPB aLY aMU aNT diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 9d36d26f6f..e8af6a21b5 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -3807,7 +3807,8 @@ movement_type = 1; name = "Sergeant Araneus"; real_name = "Sergeant Araneus"; - response_help = "pets"; + response_help_continuous = "pets"; + response_help_simple = "pet"; turns_per_move = 10 }, /turf/open/floor/carpet, @@ -6660,9 +6661,7 @@ /obj/structure/cable/yellow{ icon_state = "2-8" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /turf/open/floor/plasteel/showroomfloor, /area/security/warden) "amc" = ( @@ -7778,9 +7777,6 @@ "aop" = ( /obj/structure/bed, /obj/item/bedsheet, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 9 - }, /obj/structure/disposalpipe/segment{ dir = 4 }, @@ -7792,6 +7788,9 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/white, /area/security/brig) "aoq" = ( @@ -9147,6 +9146,7 @@ /area/maintenance/port/fore) "aqY" = ( /obj/machinery/computer/security/labor, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/dark, /area/security/brig) "aqZ" = ( @@ -10144,14 +10144,6 @@ /obj/structure/chair, /turf/open/floor/plasteel/grimy, /area/security/main) -"asN" = ( -/obj/structure/chair, -/obj/machinery/computer/security/telescreen/interrogation{ - dir = 1; - pixel_y = -30 - }, -/turf/open/floor/plasteel/grimy, -/area/security/main) "asO" = ( /obj/item/paper_bin{ pixel_x = -3; @@ -10708,7 +10700,9 @@ /turf/open/floor/plating, /area/security/main) "atZ" = ( -/obj/effect/spawner/structure/window/reinforced/tinted, +/obj/effect/spawner/structure/window/reinforced/tinted/electrochromatic{ + electrochromatic_id = "!interrogation_room" + }, /turf/open/floor/plating, /area/security/main) "aua" = ( @@ -11924,9 +11918,6 @@ /turf/open/floor/plating, /area/maintenance/fore) "awC" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 1 - }, /obj/machinery/light/small{ dir = 1 }, @@ -14823,6 +14814,9 @@ /obj/structure/cable/yellow{ icon_state = "2-8" }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/security/brig) "aCr" = ( @@ -14830,6 +14824,9 @@ name = "Court Cell"; req_access_txt = "63" }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/security/brig) "aCs" = ( @@ -45054,7 +45051,7 @@ /turf/open/floor/plating, /area/maintenance/port) "bLe" = ( -/obj/machinery/vending/autodrobe/all_access, +/obj/machinery/vending/autodrobe, /turf/open/floor/plating, /area/maintenance/port) "bLf" = ( @@ -46092,7 +46089,7 @@ /area/bridge/showroom/corporate) "bNg" = ( /obj/machinery/light_switch{ - pixel_y = 24 + pixel_y = 25 }, /obj/machinery/light/small{ dir = 1 @@ -52691,7 +52688,9 @@ /area/maintenance/starboard) "caX" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/machinery/light_switch, +/obj/machinery/light_switch{ + pixel_y = 25 + }, /turf/closed/wall, /area/maintenance/disposal/incinerator) "caY" = ( @@ -56944,21 +56943,12 @@ }, /area/science/research) "ciS" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 4 - }, -/mob/living/simple_animal/pet/dog/pug{ - desc = "It's Pugley IV, the research department's lovable pug clone. Hopefully nothing happens to this one - fourth time lucky!"; - name = "Pugley IV"; - real_name = "Pugley IV" - }, +/obj/machinery/rnd/bepis, /turf/open/floor/engine, /area/science/explab) "ciT" = ( /obj/item/beacon, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 10 - }, +/obj/machinery/atmospherics/components/unary/vent_pump/on, /turf/open/floor/engine, /area/science/explab) "ciU" = ( @@ -57077,7 +57067,7 @@ /turf/open/floor/plating/airless, /area/engine/atmos) "cjp" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/open/floor/wood, /area/maintenance/port/aft) "cjq" = ( @@ -59557,6 +59547,11 @@ /obj/structure/chair/office/light{ dir = 4 }, +/mob/living/simple_animal/pet/dog/pug{ + desc = "It's Pugley IV, the research department's lovable pug clone. Hopefully nothing happens to this one - fourth time lucky!"; + name = "Pugley IV"; + real_name = "Pugley IV" + }, /turf/open/floor/plasteel/white, /area/science/explab) "com" = ( @@ -62405,7 +62400,7 @@ dir = 10 }, /obj/machinery/light_switch{ - pixel_y = 24 + pixel_y = 25 }, /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ @@ -63920,7 +63915,7 @@ dir = 8 }, /obj/machinery/light_switch{ - pixel_y = 24 + pixel_y = 25 }, /obj/effect/turf_decal/tile/blue{ dir = 1 @@ -63928,9 +63923,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, -/obj/machinery/chem_dispenser{ - layer = 2.7 - }, +/obj/machinery/chem_dispenser/apothecary, /turf/open/floor/plasteel/white, /area/medical/medbay/aft) "cwp" = ( @@ -66312,6 +66305,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, +/obj/structure/sign/warning/biohazard, /turf/closed/wall, /area/science/mixing) "cAM" = ( @@ -66337,14 +66331,6 @@ /obj/structure/chair{ dir = 4 }, -/obj/machinery/computer/security/telescreen{ - desc = "Used for watching the test chamber."; - dir = 8; - layer = 4; - name = "Test Chamber Telescreen"; - network = list("toxins"); - pixel_x = 30 - }, /obj/effect/turf_decal/stripes/line{ dir = 5 }, @@ -66768,14 +66754,6 @@ pixel_x = 24; pixel_y = -24 }, -/obj/machinery/computer/security/telescreen{ - desc = "Used for watching the test chamber."; - dir = 8; - layer = 4; - name = "Test Chamber Telescreen"; - network = list("toxins"); - pixel_x = 30 - }, /obj/effect/turf_decal/stripes/line{ dir = 6 }, @@ -67188,6 +67166,15 @@ req_access_txt = "7" }, /obj/effect/turf_decal/loading_area, +/obj/machinery/computer/security/telescreen{ + desc = "Used for watching the test chamber."; + dir = 4; + layer = 4; + name = "Test Chamber Telescreen"; + network = list("toxins"); + pixel_x = -32; + pixel_y = 0 + }, /turf/open/floor/plasteel, /area/science/mixing) "cCH" = ( @@ -74543,7 +74530,7 @@ dir = 8 }, /obj/machinery/light_switch{ - pixel_x = -23 + pixel_y = 25 }, /obj/effect/turf_decal/stripes/line{ dir = 9 @@ -79861,13 +79848,13 @@ c_tag = "Chapel - Funeral Parlour"; dir = 8 }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/chapel/main) "djk" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 5 - }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /turf/closed/wall, /area/chapel/main) "djr" = ( @@ -80610,10 +80597,12 @@ /area/security/brig) "dBH" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/structure/cable/yellow{ icon_state = "0-4" }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 8 + }, /turf/open/floor/plating, /area/security/brig) "dBI" = ( @@ -81872,6 +81861,14 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/port) +"kRi" = ( +/obj/structure/chair, +/obj/machinery/button/electrochromatic{ + id = "!interrogation_room"; + pixel_x = -25 + }, +/turf/open/floor/plasteel/grimy, +/area/security/main) "kVo" = ( /obj/structure/cable/yellow{ icon_state = "1-2" @@ -82162,6 +82159,12 @@ /obj/item/storage/fancy/candle_box, /turf/open/floor/engine/cult, /area/library) +"oaM" = ( +/obj/machinery/computer/security/telescreen/interrogation{ + pixel_y = 32 + }, +/turf/open/floor/plasteel/grimy, +/area/security/main) "obb" = ( /obj/structure/target_stake, /obj/effect/turf_decal/stripes/line{ @@ -82215,6 +82218,10 @@ /obj/machinery/status_display/supply, /turf/closed/wall, /area/quartermaster/sorting) +"orJ" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/closed/wall, +/area/security/brig) "oub" = ( /obj/structure/sign/poster/official/random, /turf/closed/wall, @@ -82299,6 +82306,12 @@ }, /turf/closed/wall/r_wall, /area/maintenance/disposal/incinerator) +"pvk" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/closed/wall/r_wall, +/area/security/detectives_office) "pvA" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -99936,7 +99949,7 @@ aIg aIg aKN dIs -aIg +aUe dIs aQg aIg @@ -104390,7 +104403,7 @@ cLa cPF cQb djj -djr +cQb cRq cPA aaa @@ -107370,7 +107383,7 @@ akv alO anf aop -ahx +orJ aqY asn atK @@ -112777,7 +112790,7 @@ axp dBF azO aBi -ajm +axw ajm ajm ajm @@ -113291,7 +113304,7 @@ axr ayF ayF ayF -ayF +pvk ayJ ayJ aGt @@ -115339,7 +115352,7 @@ aiJ aoK aqa arv -asM +kRi atZ avk aww @@ -115595,8 +115608,8 @@ amr anD aoL ajD -arv -asN +oaM +asM atZ avk awx @@ -118507,7 +118520,7 @@ krD czD cAL cBG -cyy +czD czD czD cFu diff --git a/_maps/map_files/Mining/Lavaland.dmm b/_maps/map_files/Mining/Lavaland.dmm index 97984fa656..085522a4a5 100644 --- a/_maps/map_files/Mining/Lavaland.dmm +++ b/_maps/map_files/Mining/Lavaland.dmm @@ -2367,9 +2367,7 @@ /obj/item/seeds/cotton{ yield = 5 }, -/obj/item/seeds/cotton{ - yield = 5 - }, +/obj/item/seeds/cotton/durathread, /turf/open/indestructible/boss, /area/ruin/unpowered/ash_walkers) "Vj" = ( diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm index 8a951881f9..4fbfabaf2b 100644 --- a/_maps/map_files/OmegaStation/OmegaStation.dmm +++ b/_maps/map_files/OmegaStation/OmegaStation.dmm @@ -2150,11 +2150,6 @@ /obj/machinery/status_display/supply, /turf/closed/wall, /area/quartermaster/storage) -"adq" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/sign/warning/vacuum, -/turf/open/floor/plating, -/area/quartermaster/storage) "adr" = ( /obj/structure/cable{ icon_state = "4-8" @@ -37688,6 +37683,10 @@ /obj/machinery/atmospherics/miner/carbon_dioxide, /turf/open/floor/engine/co2, /area/engine/atmos) +"hQH" = ( +/obj/structure/sign/warning/vacuum, +/turf/closed/wall, +/area/quartermaster/storage) "hTn" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/machinery/door/airlock/research/glass{ @@ -38292,14 +38291,6 @@ /obj/structure/flora/ausbushes/ywflowers, /turf/open/floor/grass, /area/hallway/secondary/entry) -"lvt" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/sign/warning/vacuum, -/obj/machinery/light{ - dir = 4 - }, -/turf/open/floor/plating, -/area/quartermaster/storage) "lvw" = ( /obj/machinery/atmospherics/pipe/simple/orange/visible, /obj/effect/decal/cleanable/dirt, @@ -91224,7 +91215,7 @@ aac swM aeh agB -ado +adn agB ahq adp @@ -91478,13 +91469,13 @@ aaa aaa aaa aaa -adq +ado aeg aeX -adp +hQH agC ahr -lvt +ado aae aae aae diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index 4a14660e57..2c7d68d692 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -4058,6 +4058,7 @@ pixel_y = -3 }, /obj/item/gun/energy/e_gun/advtaser, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, /turf/open/floor/plasteel/dark, /area/security/armory) "akM" = ( @@ -20115,20 +20116,6 @@ /obj/machinery/conveyor_switch/oneway{ id = "QMLoad" }, -/obj/machinery/button/door{ - id = "QMLoaddoor2"; - layer = 4; - name = "Loading Doors"; - pixel_x = 24; - pixel_y = -8 - }, -/obj/machinery/button/door{ - id = "QMLoaddoor"; - layer = 4; - name = "Loading Doors"; - pixel_x = 24; - pixel_y = 8 - }, /obj/machinery/camera{ c_tag = "Cargo Supply Dock"; dir = 8 @@ -21567,6 +21554,20 @@ /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/machinery/button/door{ + id = "QMLoaddoor2"; + layer = 4; + name = "Loading Doors"; + pixel_x = 24; + pixel_y = -8 + }, +/obj/machinery/button/door{ + id = "QMLoaddoor"; + layer = 4; + name = "Loading Doors"; + pixel_x = 24; + pixel_y = 8 + }, /turf/open/floor/plasteel, /area/quartermaster/storage) "aYC" = ( @@ -38016,6 +38017,7 @@ icon_state = "4-8" }, /obj/effect/turf_decal/stripes/line, +/obj/machinery/pipedispenser, /turf/open/floor/engine, /area/science/storage) "bII" = ( @@ -38028,12 +38030,14 @@ /obj/effect/turf_decal/stripes/corner{ dir = 1 }, +/obj/machinery/pipedispenser/disposal, /turf/open/floor/engine, /area/science/storage) "bIJ" = ( /obj/structure/cable{ icon_state = "1-8" }, +/obj/machinery/pipedispenser/disposal/transit_tube, /turf/open/floor/engine, /area/science/storage) "bIK" = ( @@ -38987,6 +38991,8 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/structure/reagent_dispensers/watertank/high, +/obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, /area/engine/atmos) "bKT" = ( @@ -39005,6 +39011,10 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/structure/reagent_dispensers/fueltank, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bKU" = ( @@ -39052,9 +39062,6 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bKW" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 4 - }, /obj/structure/cable{ icon_state = "1-8" }, @@ -39067,11 +39074,15 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bKX" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 4 +/obj/machinery/atmospherics/components/binary/pump{ + dir = 0; + name = "Mix to Engine" }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -39090,10 +39101,10 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bKZ" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/layer_manifold{ dir = 4 }, -/obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/engine/atmos) "bLa" = ( @@ -39476,6 +39487,9 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bLZ" = ( @@ -39547,6 +39561,7 @@ /obj/machinery/atmospherics/pipe/manifold/yellow/visible{ dir = 4 }, +/obj/machinery/meter, /turf/open/floor/plasteel, /area/engine/atmos) "bMf" = ( @@ -39556,6 +39571,9 @@ /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bMh" = ( @@ -39570,6 +39588,9 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bMi" = ( @@ -40010,53 +40031,49 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bNd" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ - dir = 4 - }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bNe" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 6 +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 10 }, /turf/open/floor/plasteel, /area/engine/atmos) "bNf" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, +/obj/item/beacon, /turf/open/floor/plasteel, /area/engine/atmos) "bNg" = ( -/obj/machinery/atmospherics/components/binary/pump/on{ - dir = 1; - name = "Air to Distro" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/supply/visible{ + dir = 5 }, /turf/open/floor/plasteel, /area/engine/atmos) "bNh" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 }, +/obj/machinery/atmospherics/components/binary/pump{ + name = "Mix to Ports" + }, /turf/open/floor/plasteel, /area/engine/atmos) "bNi" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 8 +/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ + dir = 4 }, +/obj/machinery/meter, /turf/open/floor/plasteel, /area/engine/atmos) "bNj" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 6 - }, /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 8; + name = "Mix to Ports" + }, /turf/open/floor/plasteel, /area/engine/atmos) "bNk" = ( @@ -40066,13 +40083,13 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bNl" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 4 - }, /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/manifold/green/visible{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bNm" = ( @@ -40463,81 +40480,75 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/vending/wardrobe/atmos_wardrobe, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bOj" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 }, -/obj/machinery/door/firedoor/heavy, -/obj/machinery/door/airlock/atmos/glass{ - name = "Atmospherics Monitoring"; - req_access_txt = "24" - }, -/turf/open/floor/plasteel, +/turf/closed/wall, /area/engine/atmos) "bOk" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 }, +/obj/machinery/space_heater, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bOl" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 + dir = 10 + }, +/obj/machinery/space_heater, +/obj/effect/turf_decal/stripes/line{ + dir = 5 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bOm" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ + dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel, /area/engine/atmos) "bOn" = ( -/obj/machinery/atmospherics/pipe/manifold/cyan/visible, +/obj/machinery/atmospherics/pipe/simple/general/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bOo" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/components/binary/pump{ - name = "Mix to Port" - }, +/obj/machinery/atmospherics/pipe/manifold/general/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bOp" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1; - name = "Pure to Mix" - }, /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/simple/general/visible{ + dir = 10 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bOq" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/components/binary/pump/on{ +/obj/machinery/atmospherics/components/binary/pump{ dir = 1; - name = "Unfiltered to Mix" + name = "Pure to Mix" }, /turf/open/floor/plasteel, /area/engine/atmos) "bOr" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 10 +/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ + dir = 1 }, -/turf/open/floor/plating, +/turf/open/floor/plasteel, /area/engine/atmos) "bOs" = ( /obj/structure/sign/warning/fire, @@ -40740,133 +40751,65 @@ /area/engine/atmos) "bOQ" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 + dir = 10 }, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/turf/open/floor/plasteel, +/turf/closed/wall, /area/engine/atmos) "bOR" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 10 }, -/turf/closed/wall/r_wall, +/turf/open/floor/plating, /area/engine/atmos) "bOS" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/machinery/camera{ - c_tag = "Atmospherics Monitoring"; - dir = 1 - }, -/obj/machinery/space_heater, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/turf/open/floor/plasteel, +/obj/effect/turf_decal/vg_decals/atmos/mix, +/turf/open/floor/engine/vacuum, /area/engine/atmos) "bOT" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 5 }, -/turf/open/floor/plasteel, +/turf/closed/wall, /area/engine/atmos) "bOU" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ +/obj/machinery/atmospherics/components/binary/pump/on{ + name = "Waste to Filter" + }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) "bOV" = ( -/obj/structure/table, -/obj/item/clothing/head/welding{ - pixel_x = -3; - pixel_y = 7 - }, -/obj/item/clothing/head/welding{ - pixel_x = -5; - pixel_y = 3 - }, -/obj/item/multitool{ - layer = 4 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bOW" = ( -/obj/structure/table, -/obj/item/stack/sheet/glass/fifty, -/obj/item/storage/belt/utility, -/obj/item/t_scanner, -/obj/item/t_scanner, -/obj/item/t_scanner, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 +/obj/machinery/atmospherics/components/binary/pump/on{ + dir = 8; + name = "Air to External" }, /turf/open/floor/plasteel, /area/engine/atmos) "bOX" = ( -/obj/structure/table, -/obj/item/stack/sheet/metal/fifty, -/obj/item/stack/sheet/metal/fifty{ - pixel_x = 2; - pixel_y = 2 - }, -/obj/item/stack/sheet/glass, -/obj/item/stack/rods/fifty, -/obj/item/pipe_dispenser, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bOY" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 8 +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) "bOZ" = ( -/obj/machinery/meter, -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 9 }, /turf/open/floor/plasteel, /area/engine/atmos) "bPa" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ +/obj/machinery/portable_atmospherics/canister, +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ dir = 1 }, /turf/open/floor/plasteel, /area/engine/atmos) -"bPb" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 8; - name = "Pure to Port" - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bPc" = ( -/obj/machinery/atmospherics/pipe/manifold4w/yellow/visible, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "bPd" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible, -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 4 +/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ + dir = 8 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -40879,14 +40822,15 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bPf" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible, -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/layer_manifold{ dir = 4 }, -/obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/engine/atmos) "bPg" = ( @@ -41104,60 +41048,76 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bPO" = ( -/obj/structure/disposalpipe/segment, +/obj/structure/disposalpipe/sorting/mail{ + sortType = 6 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bPP" = ( -/obj/structure/tank_dispenser, -/obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/structure/closet/secure_closet/atmospherics, +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 8 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bPQ" = ( /turf/closed/wall, /area/engine/atmos) "bPR" = ( -/obj/machinery/atmospherics/components/binary/pump/on{ - name = "Waste In" +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 }, -/turf/open/floor/plasteel, +/turf/closed/wall, /area/engine/atmos) "bPS" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/obj/machinery/camera{ + c_tag = "Atmospherics Central"; + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bPT" = ( -/obj/machinery/atmospherics/components/binary/pump{ - name = "Air to Port" - }, -/obj/machinery/light{ - dir = 8 - }, -/obj/structure/extinguisher_cabinet{ - pixel_x = -27 +/obj/machinery/atmospherics/components/binary/pump/on{ + dir = 8; + name = "Air to Distro" }, /turf/open/floor/plasteel, /area/engine/atmos) "bPU" = ( /obj/machinery/atmospherics/components/binary/pump{ - name = "Mix to Port" + name = "Air to Ports" }, /turf/open/floor/plasteel, /area/engine/atmos) "bPV" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible, /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/simple/general/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bPW" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible, +/obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bPX" = ( @@ -41172,6 +41132,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bPY" = ( @@ -41186,14 +41147,14 @@ /turf/open/floor/engine/n2o, /area/engine/atmos) "bQa" = ( -/obj/machinery/portable_atmospherics/canister/nitrous_oxide, -/obj/machinery/atmospherics/miner/n2o, +/obj/effect/turf_decal/vg_decals/atmos/nitrous_oxide, /turf/open/floor/engine/n2o, /area/engine/atmos) "bQb" = ( /obj/machinery/light/small{ dir = 4 }, +/obj/machinery/atmospherics/miner/n2o, /turf/open/floor/engine/n2o, /area/engine/atmos) "bQc" = ( @@ -41496,10 +41457,6 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bQF" = ( -/obj/structure/chair/office/dark{ - dir = 8 - }, -/obj/effect/landmark/start/atmospheric_technician, /obj/effect/turf_decal/tile/yellow{ dir = 1 }, @@ -41509,54 +41466,48 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bQG" = ( -/obj/machinery/computer/atmos_control{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel, /area/engine/atmos) "bQH" = ( -/obj/machinery/pipedispenser, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow, /turf/open/floor/plasteel, /area/engine/atmos) "bQI" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, -/turf/open/floor/plasteel, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/closed/wall, /area/engine/atmos) "bQJ" = ( -/obj/structure/closet/secure_closet/atmospherics, -/obj/effect/turf_decal/stripes/line{ - dir = 8 +/obj/machinery/atmospherics/components/binary/pump{ + dir = 8; + name = "Ports to Filter" }, /turf/open/floor/plasteel, /area/engine/atmos) "bQK" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ +/obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 4 }, -/obj/machinery/portable_atmospherics/canister, -/obj/effect/turf_decal/bot, +/obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bQL" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 4 - }, +/obj/machinery/atmospherics/pipe/manifold4w/general/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bQM" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 8 +/obj/effect/turf_decal/tile/yellow, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 }, -/obj/effect/turf_decal/bot, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bQN" = ( -/obj/machinery/atmospherics/components/trinary/filter/atmos/n2o{ - dir = 1 +/obj/machinery/atmospherics/components/binary/pump/on{ + dir = 1; + name = "Unfiltered to Mix" }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -41830,105 +41781,88 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "bRr" = ( -/obj/structure/table/reinforced, -/obj/machinery/door/firedoor/heavy, -/obj/machinery/door/window/northleft{ - dir = 4; - name = "Atmospherics Desk"; - req_access_txt = "24" - }, -/obj/machinery/door/poddoor/preopen{ - id = "atmos"; - name = "atmospherics security door" - }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/effect/turf_decal/delivery, -/turf/open/floor/plasteel, +/turf/closed/wall/r_wall, /area/engine/atmos) "bRs" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/structure/chair/office/dark{ - dir = 8 - }, -/obj/effect/landmark/start/atmospheric_technician, /obj/effect/turf_decal/tile/yellow{ dir = 1 }, /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/structure/tank_dispenser, /turf/open/floor/plasteel, /area/engine/atmos) "bRt" = ( /obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10 +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 1 }, /turf/open/floor/plasteel, /area/engine/atmos) "bRu" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) +"bRw" = ( +/obj/machinery/atmospherics/pipe/manifold4w/general/visible, +/obj/machinery/meter, +/turf/open/floor/plasteel, +/area/engine/atmos) +"bRx" = ( +/obj/machinery/computer/atmos_control, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) +"bRy" = ( +/obj/structure/closet/secure_closet/atmospherics, /obj/machinery/requests_console{ department = "Atmospherics"; departmentType = 4; name = "Atmos RC"; pixel_x = 30 }, -/obj/machinery/light{ - dir = 4 - }, -/obj/machinery/computer/atmos_alert{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bRv" = ( -/obj/machinery/pipedispenser/disposal, -/obj/machinery/light{ - dir = 8 - }, -/obj/machinery/camera{ - c_tag = "Atmospherics Central"; - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bRw" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ +/obj/effect/turf_decal/tile/yellow{ dir = 1 }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bRx" = ( -/obj/machinery/suit_storage_unit/atmos, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bRy" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ +/obj/effect/turf_decal/tile/yellow, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/machinery/meter, +/obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, /area/engine/atmos) "bRz" = ( +/obj/structure/disposalpipe/segment, /obj/machinery/holopad, /turf/open/floor/plasteel, /area/engine/atmos) "bRA" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 8 +/obj/structure/chair/office/dark{ + dir = 1 }, -/obj/machinery/meter, +/obj/effect/landmark/start/atmospheric_technician, /turf/open/floor/plasteel, /area/engine/atmos) "bRB" = ( @@ -41939,6 +41873,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bRC" = ( @@ -42177,6 +42112,11 @@ id = "atmos"; name = "atmospherics security door" }, +/obj/machinery/door/window/northleft{ + dir = 4; + name = "Atmospherics Desk"; + req_access_txt = "24" + }, /turf/open/floor/plasteel, /area/engine/atmos) "bSb" = ( @@ -42189,76 +42129,70 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/conveyor_switch{ + id = "atmosdeliver" + }, /turf/open/floor/plasteel, /area/engine/atmos) "bSc" = ( -/obj/structure/disposalpipe/sorting/mail/flip{ - dir = 2; - sortType = 6 +/obj/effect/turf_decal/tile/yellow, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 1 }, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, +/obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, /area/engine/atmos) "bSd" = ( -/obj/machinery/disposal/bin, -/obj/structure/disposalpipe/trunk{ +/obj/effect/turf_decal/tile/yellow, +/obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/suit_storage_unit/atmos, +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel, +/area/engine/atmos) +"bSe" = ( +/obj/machinery/suit_storage_unit/atmos, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ dir = 8 }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bSe" = ( -/obj/machinery/pipedispenser/disposal/transit_tube, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bSf" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 4 - }, -/obj/item/wrench, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bSg" = ( -/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, +/obj/machinery/light{ dir = 8 }, -/obj/structure/cable{ - icon_state = "1-2" - }, /turf/open/floor/plasteel, /area/engine/atmos) "bSh" = ( -/obj/machinery/camera{ - c_tag = "Atmospherics Starboard"; - dir = 8 - }, /obj/machinery/atmospherics/components/binary/pump{ dir = 8; name = "Plasma Outlet Pump" }, /obj/effect/turf_decal/tile/yellow, +/obj/machinery/atmospherics/pipe/simple/green/visible, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) -"bSi" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible, -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 4 - }, -/turf/open/floor/plating, -/area/engine/atmos) "bSj" = ( /obj/machinery/atmospherics/components/unary/vent_pump/siphon/on{ dir = 8; @@ -42530,31 +42464,42 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bSR" = ( -/obj/machinery/light{ - dir = 8 +/obj/effect/turf_decal/tile/yellow, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 }, -/obj/machinery/atmospherics/components/binary/pump{ - name = "Port to Filter" - }, -/obj/structure/extinguisher_cabinet{ - pixel_x = -27 +/obj/machinery/atmospherics/components/trinary/filter/atmos/n2o{ + dir = 1 }, /turf/open/floor/plasteel, /area/engine/atmos) "bSS" = ( -/obj/item/beacon, +/obj/structure/chair/office/dark, +/obj/effect/landmark/start/atmospheric_technician, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 10 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bST" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ +/obj/machinery/computer/atmos_alert{ + dir = 1 + }, +/obj/effect/turf_decal/tile/yellow{ dir = 8 }, -/obj/structure/chair/stool, +/obj/effect/turf_decal/tile/yellow, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 5 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bSU" = ( /obj/machinery/atmospherics/components/unary/thermomachine/heater{ - dir = 8 + dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -42570,6 +42515,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bSW" = ( @@ -42579,14 +42525,14 @@ /turf/open/floor/engine/plasma, /area/engine/atmos) "bSX" = ( -/obj/machinery/portable_atmospherics/canister/toxins, -/obj/machinery/atmospherics/miner/toxins, +/obj/effect/turf_decal/vg_decals/atmos/plasma, /turf/open/floor/engine/plasma, /area/engine/atmos) "bSY" = ( /obj/machinery/light/small{ dir = 4 }, +/obj/machinery/atmospherics/miner/toxins, /turf/open/floor/engine/plasma, /area/engine/atmos) "bSZ" = ( @@ -42922,19 +42868,22 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 6 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bTI" = ( /obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 6 - }, /obj/effect/turf_decal/tile/yellow{ dir = 1 }, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bTJ" = ( @@ -42947,6 +42896,9 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bTK" = ( @@ -42986,87 +42938,72 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bTM" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bTN" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 4 - }, -/obj/item/radio/intercom{ - name = "Station Intercom (General)"; - pixel_x = 30; - pixel_y = 26 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bTO" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 4 - }, -/obj/machinery/vending/wardrobe/atmos_wardrobe, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bTP" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 4 - }, -/obj/structure/reagent_dispensers/watertank/high, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/structure/fireaxecabinet{ - pixel_y = 32 + pixel_x = -32 }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bTQ" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 4 - }, -/obj/structure/reagent_dispensers/fueltank, -/obj/machinery/camera{ - c_tag = "Atmospherics Mixing" - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bTR" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 8; - name = "Port to Filter" - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bTS" = ( -/obj/item/cigbutt, -/obj/machinery/atmospherics/pipe/manifold4w/general/visible, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bTT" = ( -/obj/machinery/atmospherics/components/unary/thermomachine/freezer{ +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 8 }, /turf/open/floor/plasteel, /area/engine/atmos) -"bTU" = ( +"bTN" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 9 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) +"bTO" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plating, +/area/engine/atmos) +"bTP" = ( +/obj/effect/turf_decal/tile/yellow, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, /obj/machinery/atmospherics/components/trinary/filter/atmos/plasma{ dir = 1 }, +/obj/machinery/camera{ + c_tag = "Atmospherics Starboard"; + dir = 8 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) +"bTQ" = ( +/obj/machinery/door/poddoor/preopen{ + id = "atmos"; + name = "atmospherics security door" + }, +/obj/machinery/door/firedoor/heavy, +/obj/effect/turf_decal/delivery, +/obj/structure/closet/firecloset, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel, +/area/engine/atmos) +"bTR" = ( +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/orange/visible, +/turf/open/floor/plasteel, +/area/engine/atmos) +"bTS" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/purple/visible, +/turf/open/floor/plasteel, +/area/engine/atmos) +"bTT" = ( +/obj/machinery/atmospherics/components/unary/thermomachine/freezer{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bTV" = ( @@ -43213,9 +43150,6 @@ /obj/machinery/camera{ c_tag = "Engineering Access" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 - }, /obj/item/radio/intercom{ name = "Station Intercom (General)"; pixel_y = 24 @@ -43239,89 +43173,86 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bUp" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 6 - }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bUq" = ( /obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ - dir = 4 - }, /turf/open/floor/plasteel, /area/engine/atmos) "bUr" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 9 }, +/obj/machinery/meter, /turf/open/floor/plasteel, /area/engine/atmos) "bUs" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 }, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 1; + name = "O2 to Pure" + }, /turf/open/floor/plasteel, /area/engine/atmos) "bUt" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 8 - }, +/obj/machinery/atmospherics/pipe/simple/orange/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bUu" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bUv" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 4; - name = "incinerator mix pump" - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bUw" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible, /obj/structure/cable{ icon_state = "1-2" }, /obj/machinery/atmospherics/pipe/simple/purple/visible{ - dir = 4 + dir = 5 }, /turf/open/floor/plasteel, /area/engine/atmos) -"bUx" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible, -/obj/machinery/atmospherics/pipe/simple/purple/visible{ +"bUv" = ( +/obj/machinery/atmospherics/pipe/simple/general/visible{ + dir = 6 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) +"bUw" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/manifold/general/visible{ dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) "bUy" = ( -/obj/machinery/atmospherics/pipe/simple/purple/visible{ - dir = 4 - }, /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bUz" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, -/obj/machinery/atmospherics/pipe/simple/purple/visible{ +/obj/effect/turf_decal/tile/yellow, +/obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/turf/open/floor/plating, +/obj/machinery/atmospherics/components/trinary/filter/atmos/co2{ + dir = 1 + }, +/turf/open/floor/plasteel, /area/engine/atmos) "bUA" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/simple/purple/visible{ - dir = 10 +/obj/effect/turf_decal/tile/yellow, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 }, -/turf/open/space, -/area/space/nearstation) +/obj/machinery/atmospherics/components/trinary/filter/atmos/o2{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "bUC" = ( /obj/structure/flora/ausbushes/fernybush, /turf/open/floor/plating/asteroid, @@ -43613,12 +43544,12 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 9 - }, /obj/effect/turf_decal/stripes/line{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/break_room) "bVc" = ( @@ -43630,10 +43561,8 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 8 - }, /obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/manifold4w/scrubbers, /turf/open/floor/plasteel, /area/engine/atmos) "bVd" = ( @@ -43663,35 +43592,42 @@ /obj/structure/disposalpipe/segment{ dir = 9 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bVg" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 4 +/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ + dir = 8 }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/yellow, /turf/open/floor/plasteel, /area/engine/atmos) "bVh" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 6 +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ + dir = 8 }, -/turf/open/floor/plasteel, +/turf/open/floor/plating, /area/engine/atmos) "bVi" = ( -/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ - dir = 1 +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 5 }, -/turf/open/floor/plasteel, +/turf/open/floor/plating, /area/engine/atmos) "bVj" = ( /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/manifold/yellow/visible, +/obj/machinery/atmospherics/components/binary/pump{ + name = "incinerator mix pump" + }, /turf/open/floor/plasteel, /area/engine/atmos) "bVk" = ( @@ -43703,24 +43639,25 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bVl" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ +/obj/machinery/atmospherics/pipe/simple/cyan/visible, +/obj/machinery/atmospherics/pipe/layer_manifold{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plating, /area/engine/atmos) "bVm" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/green/visible{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/purple/visible, -/turf/open/space, -/area/space/nearstation) +/obj/machinery/atmospherics/pipe/layer_manifold, +/turf/open/floor/plating, +/area/engine/atmos) "bVn" = ( /obj/machinery/atmospherics/components/unary/vent_pump/siphon/atmos/carbon_output{ dir = 8 @@ -44008,44 +43945,21 @@ }, /turf/open/floor/plasteel, /area/engine/break_room) -"bVV" = ( -/obj/machinery/atmospherics/components/binary/pump{ - name = "Waste to Space" - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "bVW" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 9 }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bVX" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 6 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) +/turf/closed/wall/r_wall, +/area/maintenance/disposal/incinerator) "bVY" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1; - name = "O2 to Pure" +/obj/machinery/atmospherics/pipe/manifold/yellow/visible{ + dir = 1 }, /turf/open/floor/plasteel, /area/engine/atmos) "bVZ" = ( -/obj/machinery/atmospherics/pipe/manifold/cyan/visible{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bWa" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 4; - name = "N2 to Pure" +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 4 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -44057,6 +43971,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bWc" = ( @@ -44064,24 +43979,19 @@ /obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plating, /area/engine/atmos) -"bWd" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/simple/purple/visible, -/turf/open/space, -/area/space/nearstation) "bWe" = ( /obj/machinery/air_sensor/atmos/carbon_tank, /turf/open/floor/engine/co2, /area/engine/atmos) "bWf" = ( -/obj/machinery/portable_atmospherics/canister/carbon_dioxide, -/obj/machinery/atmospherics/miner/carbon_dioxide, +/obj/effect/turf_decal/vg_decals/atmos/carbon_dioxide, /turf/open/floor/engine/co2, /area/engine/atmos) "bWg" = ( /obj/machinery/light/small{ dir = 4 }, +/obj/machinery/atmospherics/miner/carbon_dioxide, /turf/open/floor/engine/co2, /area/engine/atmos) "bWh" = ( @@ -44398,43 +44308,34 @@ /area/engine/break_room) "bWI" = ( /obj/machinery/portable_atmospherics/scrubber, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bWJ" = ( /obj/machinery/portable_atmospherics/pump, /obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 10 + }, +/obj/effect/turf_decal/stripes/line{ dir = 5 }, /turf/open/floor/plasteel, /area/engine/atmos) -"bWK" = ( -/obj/machinery/atmospherics/components/trinary/filter/atmos/o2{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bWL" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "bWM" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bWN" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 10 +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 6 }, /turf/open/floor/plasteel, /area/engine/atmos) "bWO" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 10 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bWP" = ( @@ -44445,8 +44346,8 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bWQ" = ( -/obj/machinery/atmospherics/components/trinary/filter/atmos/co2{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/purple/visible{ + dir = 10 }, /turf/open/floor/plasteel, /area/engine/atmos) @@ -44458,14 +44359,6 @@ /obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plating, /area/engine/atmos) -"bWS" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/purple/visible, -/turf/open/space, -/area/space/nearstation) "bWT" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/atmos/carbon_input{ dir = 8 @@ -44644,11 +44537,13 @@ /area/engine/engineering) "bXr" = ( /obj/machinery/portable_atmospherics/scrubber, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/components/binary/pump{ + name = "Waste to Space" + }, /turf/open/floor/plasteel, /area/engine/atmos) "bXs" = ( @@ -44657,14 +44552,22 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 5 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bXt" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible, /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/components/trinary/filter/atmos/n2{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bXu" = ( @@ -44675,6 +44578,9 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bXv" = ( @@ -44683,6 +44589,9 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bXw" = ( @@ -44691,7 +44600,10 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/orange/visible, +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/layer_manifold, /turf/open/floor/plasteel, /area/engine/atmos) "bXx" = ( @@ -44702,6 +44614,9 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/green/visible{ + dir = 10 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bXy" = ( @@ -44712,17 +44627,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, -/turf/open/floor/plasteel, -/area/engine/atmos) -"bXz" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible, -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, +/obj/machinery/meter, /turf/open/floor/plasteel, /area/engine/atmos) "bXA" = ( @@ -44753,6 +44658,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/orange/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bXD" = ( @@ -44769,7 +44675,6 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bXE" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible, /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 }, @@ -44780,6 +44685,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/purple/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bXF" = ( @@ -44793,15 +44699,13 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel, /area/engine/atmos) "bXG" = ( /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 9 }, -/obj/machinery/atmospherics/pipe/simple/purple/visible{ - dir = 6 - }, /turf/closed/wall/r_wall, /area/engine/atmos) "bXI" = ( @@ -44998,17 +44902,11 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/engine/atmos) -"bYq" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/green/visible{ - dir = 5 - }, -/turf/open/floor/plating, -/area/engine/atmos) "bYs" = ( /obj/machinery/atmospherics/pipe/simple/green/hidden{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/orange/visible, /turf/closed/wall/r_wall, /area/maintenance/disposal/incinerator) "bYt" = ( @@ -45019,9 +44917,6 @@ /turf/closed/wall, /area/maintenance/disposal/incinerator) "bYu" = ( -/obj/machinery/atmospherics/pipe/simple/green/hidden{ - dir = 9 - }, /obj/structure/cable{ icon_state = "1-2" }, @@ -45029,9 +44924,16 @@ name = "Incinerator"; req_access_txt = "24" }, +/obj/machinery/atmospherics/pipe/simple/green/hidden{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/purple/visible, /turf/open/floor/plasteel/dark, /area/maintenance/disposal/incinerator) "bYv" = ( +/obj/machinery/atmospherics/pipe/simple/green/hidden{ + dir = 9 + }, /turf/closed/wall, /area/maintenance/disposal/incinerator) "bYw" = ( @@ -45430,16 +45332,6 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) -"bZd" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/simple/green/visible, -/turf/open/space, -/area/space/nearstation) -"bZe" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/simple/cyan/visible, -/turf/open/space, -/area/space/nearstation) "bZf" = ( /obj/machinery/power/apc{ dir = 8; @@ -45479,6 +45371,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/purple/visible, /turf/open/floor/plasteel/dark, /area/maintenance/disposal/incinerator) "bZh" = ( @@ -45497,7 +45390,6 @@ /area/maintenance/disposal/incinerator) "bZi" = ( /obj/machinery/meter, -/obj/machinery/atmospherics/pipe/simple/purple/visible, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, @@ -45646,10 +45538,12 @@ /turf/open/floor/plasteel, /area/engine/engineering) "bZK" = ( -/obj/machinery/atmospherics/components/unary/outlet_injector/on{ +/obj/structure/lattice, +/obj/machinery/atmospherics/components/unary/relief_valve/atmos/atmos_waste{ dir = 1 }, -/turf/open/floor/plating/airless, +/obj/structure/lattice/catwalk, +/turf/open/space, /area/engine/atmos) "bZL" = ( /obj/machinery/atmospherics/pipe/simple, @@ -45690,6 +45584,9 @@ /obj/structure/cable/yellow{ icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/simple/purple/visible{ + dir = 5 + }, /turf/open/floor/plasteel/dark, /area/maintenance/disposal/incinerator) "bZQ" = ( @@ -45709,11 +45606,14 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/purple/visible{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/maintenance/disposal/incinerator) "bZR" = ( /obj/machinery/atmospherics/pipe/simple/purple/visible{ - dir = 5 + dir = 4 }, /turf/closed/wall/r_wall, /area/maintenance/disposal/incinerator) @@ -46166,16 +46066,14 @@ /turf/open/floor/engine/n2, /area/engine/atmos) "cbt" = ( -/obj/machinery/portable_atmospherics/canister/nitrogen, -/obj/machinery/atmospherics/miner/nitrogen, +/obj/effect/turf_decal/vg_decals/atmos/nitrogen, /turf/open/floor/engine/n2, /area/engine/atmos) "cbu" = ( /turf/open/floor/engine/o2, /area/engine/atmos) "cbv" = ( -/obj/machinery/portable_atmospherics/canister/oxygen, -/obj/machinery/atmospherics/miner/oxygen, +/obj/effect/turf_decal/vg_decals/atmos/oxygen, /turf/open/floor/engine/o2, /area/engine/atmos) "cbw" = ( @@ -46183,8 +46081,8 @@ /turf/open/floor/engine/air, /area/engine/atmos) "cbx" = ( -/obj/machinery/portable_atmospherics/canister/air, /obj/effect/landmark/event_spawn, +/obj/effect/turf_decal/vg_decals/atmos/air, /turf/open/floor/engine/air, /area/engine/atmos) "cby" = ( @@ -46385,10 +46283,12 @@ /area/engine/engineering) "ccm" = ( /obj/machinery/light/small, +/obj/machinery/atmospherics/miner/nitrogen, /turf/open/floor/engine/n2, /area/engine/atmos) "ccn" = ( /obj/machinery/light/small, +/obj/machinery/atmospherics/miner/oxygen, /turf/open/floor/engine/o2, /area/engine/atmos) "cco" = ( @@ -50093,15 +49993,15 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "cqG" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 4 - }, /obj/effect/turf_decal/tile/yellow{ dir = 1 }, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "cqH" = ( @@ -52510,6 +52410,23 @@ }, /turf/open/floor/plasteel/dark, /area/library) +"cBi" = ( +/obj/machinery/flasher/portable, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 5 + }, +/turf/open/floor/plasteel/dark, +/area/security/armory) "cBk" = ( /obj/machinery/vending/boozeomat/pubby_maint, /turf/closed/wall, @@ -52686,12 +52603,6 @@ /obj/machinery/status_display/ai, /turf/closed/wall/r_wall, /area/engine/supermatter) -"cCO" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/closed/wall, -/area/security/brig) "cCP" = ( /obj/effect/turf_decal/bot/right, /turf/open/floor/plasteel/white, @@ -53276,7 +53187,9 @@ /area/medical/chemistry) "dJk" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/orange/visible, +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 9 + }, /turf/open/floor/plating, /area/engine/atmos) "dJm" = ( @@ -53979,12 +53892,6 @@ }, /turf/open/floor/wood, /area/lawoffice) -"fuR" = ( -/obj/machinery/atmospherics/components/trinary/filter/atmos/n2{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "fvb" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable{ @@ -54801,10 +54708,9 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "hjk" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/visible{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 6 }, -/obj/machinery/atmospherics/pipe/simple/orange/visible, /turf/open/floor/plasteel, /area/engine/atmos) "hjD" = ( @@ -54818,6 +54724,17 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, /area/engine/engineering) +"hka" = ( +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow, +/obj/machinery/camera{ + c_tag = "Atmospherics Console"; + dir = 8 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "hkQ" = ( /obj/machinery/light{ dir = 4 @@ -55370,6 +55287,9 @@ /turf/open/floor/plasteel/dark, /area/science/xenobiology) "ivO" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, /mob/living/simple_animal/bot/secbot{ arrest_type = 1; health = 45; @@ -55763,6 +55683,13 @@ }, /turf/open/floor/plasteel/dark, /area/science/xenobiology) +"juw" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/security/armory) "jvi" = ( /obj/structure/cable{ icon_state = "4-8" @@ -55907,10 +55834,6 @@ }, /turf/open/floor/plating, /area/maintenance/department/crew_quarters/dorms) -"jLW" = ( -/obj/machinery/atmospherics/pipe/simple/purple/visible, -/turf/closed/wall/r_wall, -/area/maintenance/disposal/incinerator) "jOB" = ( /turf/open/floor/plating, /area/storage/emergency/starboard) @@ -56032,6 +55955,16 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/medical/chemistry) +"kas" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/yellow, +/turf/open/floor/plasteel, +/area/engine/atmos) "kaR" = ( /obj/machinery/atmospherics/components/trinary/filter/flipped/critical{ dir = 8 @@ -56559,12 +56492,6 @@ /obj/machinery/atmospherics/pipe/manifold/general/visible, /turf/open/floor/plasteel/dark, /area/science/xenobiology) -"lhP" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 9 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "liR" = ( /obj/machinery/atmospherics/pipe/simple/green/visible{ dir = 4 @@ -56579,12 +56506,6 @@ /obj/machinery/atmospherics/pipe/simple/general/hidden, /turf/open/floor/plating, /area/maintenance/department/cargo) -"ljG" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 6 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "lms" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 9 @@ -58347,6 +58268,15 @@ }, /turf/open/floor/plating, /area/security/execution/transfer) +"pfB" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/manifold/cyan/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/security/armory) "pfP" = ( /obj/structure/table, /obj/item/storage/box/syringes, @@ -58403,10 +58333,13 @@ /turf/open/floor/plasteel/dark, /area/maintenance/department/crew_quarters/dorms) "pmB" = ( -/obj/machinery/atmospherics/pipe/simple/green/visible{ +/obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/orange/visible, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 1; + name = "N2 to Pure" + }, /turf/open/floor/plasteel, /area/engine/atmos) "pnU" = ( @@ -59925,13 +59858,6 @@ }, /turf/open/floor/plasteel, /area/science/xenobiology) -"tbw" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 9 - }, -/turf/open/space, -/area/space/nearstation) "tbF" = ( /obj/structure/window/reinforced, /obj/structure/window/reinforced{ @@ -60223,13 +60149,6 @@ /obj/item/wrench, /turf/open/floor/plating, /area/maintenance/department/cargo) -"tDE" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 8; - name = "Mix to Engine" - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "tHk" = ( /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -61498,13 +61417,6 @@ }, /turf/open/floor/plating, /area/maintenance/department/engine) -"wJP" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/simple/purple/visible{ - dir = 9 - }, -/turf/open/space, -/area/space/nearstation) "wKa" = ( /obj/machinery/light/small, /turf/open/floor/plating, @@ -61520,12 +61432,6 @@ }, /turf/open/floor/plating, /area/crew_quarters/heads/cmo) -"wLK" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/atmos) "wMF" = ( /obj/effect/spawner/lootdrop/three_course_meal, /obj/effect/spawner/lootdrop/three_course_meal, @@ -84622,7 +84528,7 @@ aiL ajg ajP akL -alA +cBi amh amV anF @@ -84879,7 +84785,7 @@ aiM aiM ajQ akM -akM +juw ami amW anG @@ -85393,7 +85299,7 @@ aiN aji ajS akO -akO +pfB amk amY anI @@ -89257,7 +89163,7 @@ apj ajM ajM ajM -cCO +ajM ajM ajM avL @@ -96271,7 +96177,7 @@ bRq bCC bSP bTG -bUo +bTQ bVc bUo bWH @@ -96787,7 +96693,7 @@ bLW bTH bUp bVe -bVV +bUp bWI bXr bKQ @@ -97037,14 +96943,14 @@ bMZ bOh bOP bPO -bPO +bRz bRt bSc bSQ bTI bUq bVf -bQI +bMf bWJ bXs bJN @@ -97297,12 +97203,12 @@ bPP bQG bRu bSd -bLW +bTO bTJ bMf -bUs bMf -fuR +bMf +bMf bXt bYp eAZ @@ -97549,17 +97455,17 @@ bJN bJN bNb bOj -bOR -bJN -bJN -bJN -bJN +bPQ +bRx +bRA +bSS +bST bJN bTK -bUr -bVg -bVW -bWL +bMf +bMf +bMf +bMf bXu bLW cui @@ -97806,19 +97712,19 @@ bJN bLY bNc bOk -bOS bPQ +bRy +hka bQH -bRv bSe bPQ bTL -bUs bMf -bVX +bMf +bMf bWM bXv -bWc +bVh poP bZL caB @@ -98065,18 +97971,18 @@ bNd bOl bOT bPR +bPQ +bPQ bQI -bQI -bQI -bQI -bTM -bUs -ljG +bPQ +bNc +bMf +bMf hjk pmB bXw dJk -tbw +cui bJP bJP bJP @@ -98322,18 +98228,18 @@ bNe bOm bOU bPS -bPS -bRw -bMf -bMf +bSf +bUp +bTM +bUp bTN -bUt -wLK -bOk -bWK -bXt +bMf +bMf +bVZ +bOX +bUA bYp -bZd +eAZ bZL caC cbu @@ -98576,21 +98482,21 @@ bJL bKR bMb bNf -bOk +bQJ bOV -bPQ -bQJ -bRx -bQJ -bPQ -bTO -ljG -lhP -bOk -bWL +bMf +bMf +bMf +bMf +bMf +bMf +bMf +bMf +bVZ +bOX bXx -bLW -abI +bVi +cui bMi caD cbv @@ -98834,20 +98740,20 @@ bJN bMc bNg bOn -bOW -bPQ -bPQ -bPQ -bPQ -bPQ -bTP -wLK -bVh +bOX +bMf +bMf +bMf +bMf +bMf +bMf +bMf +bMf bVY -bWM -bXy -bWc -bZe +bUs +bVg +bVm +poP bZL caE cbu @@ -99089,22 +98995,22 @@ bIE bJN bJN bMd -bNf -bOk +bPT +bOn bOX -bPQ -bQK -bQK -bQK -bPQ -bTQ -wLK -bKX -bOk -bWN -bXz -bYq -abI +bMf +bMf +bMf +bMf +bMf +bMf +bMf +bMf +bVZ +bOX +kas +bNm +cui bJP bJP bJP @@ -99348,20 +99254,20 @@ bKS bMe bNh bOo -bOY -bPT -bQL -bRy -bSf -bSR -bTM -wLK -bKX +bOX +bMf +bMf +bMf +bMf +bMf +bMf +bMf +bMf bVZ bWO bXA bQO -bZe +poP bZM caF cbw @@ -99602,23 +99508,23 @@ aht aaa bJN bKT -bMf +bWM bNi -bOk +bQK bOZ bMf bMf -bRz bMf -bSS -bTR -tDE -bKX -bWa +bMf +bMf +bMf +bMf +bMf +bVZ bMf bXB bNm -abI +cui bMi caG cbx @@ -99859,23 +99765,23 @@ bCP bAA bHw bKU -bMf -bMf -bOk -bPa +bOr bPU -bOY -bRA -bOY -bST -bTS -bUu -bVi -bMe +bRw +bPa +bMf +bMf +bMf +bMf +bMf +bMf +bMf +bMf +bVY bWP bXy bQO -bZe +poP bZN caH cby @@ -100116,23 +100022,23 @@ bCR bIF bHw bKV +bOX +bUv +bQL +bPa +bMf bMf bMf -bOk -bPb bMf -bQM -bQM -bQM bSU bTT bUv bKX -bMf -bMf +bTR +bUt bXC bYs -bYw +bVW bYw bYw cBT @@ -100376,17 +100282,17 @@ bKW bMg bNj bOp -bPc bPV bPV bPV -bSg bPV bPV bUw +bUw +bUw bVj -bMg -bMg +bTS +bUu bXD bYt bZf @@ -100630,19 +100536,19 @@ bCR bIH bHw cqG -bMf +bOX bNk bOq bPd bPW -bQN +bPW bPW bPd bPW -bTU -bUx -bPd bPW +bPW +bPd +bUr bWQ bXE bYu @@ -100889,18 +100795,18 @@ bHw bKY bMh bNl -bOi +bQM bPe bPX -bNl +bSR bRB bSh bSV -bNl +bTP bUy bVk bWb -bNl +bUz bXF bYv bZh @@ -101144,22 +101050,22 @@ bHv bIJ bHw bKZ -bLW -bNm -bOr +bOR +bWR +bWc bPf bPY bQO bPY -bSi +bPf bPY bQO -bUz +bWc bVl bWc bWR bXG -jLW +bYw bZi bZR caL @@ -101411,11 +101317,11 @@ abI bLa abI bNn -bUA -bVm -bWd -bWS -wJP +abI +bLa +abI +bNn +abI aht bZj bZS @@ -102172,7 +102078,7 @@ buz abI bJP bLd -bLe +bOS bLe bJP bPh diff --git a/_maps/map_files/debug/multiz.dmm b/_maps/map_files/debug/multiz.dmm index 085a64bf97..3f7cacd1a8 100644 --- a/_maps/map_files/debug/multiz.dmm +++ b/_maps/map_files/debug/multiz.dmm @@ -473,12 +473,6 @@ }, /turf/open/floor/plasteel, /area/engine/gravity_generator) -"bs" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/closed/wall/r_wall, -/area/engine/gravity_generator) "bt" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 8 @@ -654,7 +648,9 @@ pixel_x = -25 }, /obj/structure/closet/firecloset/full, -/obj/structure/cable, +/obj/structure/cable{ + icon_state = "0-2" + }, /turf/open/floor/plasteel{ dir = 9 }, @@ -793,7 +789,9 @@ }, /area/hallway/primary/central) "cl" = ( -/obj/structure/cable, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plasteel{ dir = 8 }, @@ -3614,8 +3612,8 @@ ak aT ak ak -bs -bL +ak +bE bE bE cc @@ -3669,7 +3667,7 @@ aU bg bq ak -bL +bE bE bE cd @@ -3723,7 +3721,7 @@ bh bh br ak -bL +bE bE bE cc diff --git a/_maps/map_files/debug/runtimestation.dmm b/_maps/map_files/debug/runtimestation.dmm index feb8fc8cc0..0a73818ab3 100644 --- a/_maps/map_files/debug/runtimestation.dmm +++ b/_maps/map_files/debug/runtimestation.dmm @@ -2526,7 +2526,6 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 }, -/turf/open/space/basic, /turf/open/floor/carpet/blackred, /area/crew_quarters/bar) "gR" = ( @@ -2806,7 +2805,6 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/turf/open/space/basic, /turf/open/floor/carpet/blackred, /area/crew_quarters/bar) "vP" = ( @@ -2832,7 +2830,6 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "wf" = ( -/turf/open/space/basic, /turf/open/floor/carpet/blackred, /area/crew_quarters/bar) "wS" = ( @@ -2854,7 +2851,6 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/turf/open/space/basic, /turf/open/floor/carpet/blackred, /area/crew_quarters/bar) "xh" = ( @@ -2869,7 +2865,6 @@ /obj/structure/cable{ icon_state = "4-8" }, -/turf/open/space/basic, /turf/open/floor/carpet/blackred, /area/crew_quarters/bar) "yt" = ( @@ -3002,7 +2997,7 @@ /turf/open/floor/grass, /area/hydroponics) "Ga" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /obj/machinery/airalarm{ dir = 8; pixel_x = 24 @@ -3041,7 +3036,6 @@ /area/bridge) "IB" = ( /obj/structure/chair/stool/bar, -/turf/open/space/basic, /turf/open/floor/carpet/blackred, /area/crew_quarters/bar) "JF" = ( @@ -3086,7 +3080,6 @@ /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 8 }, -/turf/open/space/basic, /turf/open/floor/carpet/blackred, /area/crew_quarters/bar) "Ly" = ( @@ -3115,7 +3108,6 @@ icon_state = "1-4" }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/space/basic, /turf/open/floor/carpet/blackred, /area/crew_quarters/bar) "MS" = ( @@ -3334,7 +3326,6 @@ /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 4 }, -/turf/open/space/basic, /turf/open/floor/carpet/blackred, /area/crew_quarters/bar) @@ -9446,7 +9437,7 @@ fh fh eY eR -fh +et eR fc fh diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index d015547ac4..66072817f4 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -13278,7 +13278,7 @@ /turf/open/floor/engine/cult, /area/wizard_station) "ED" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/closed/indestructible{ icon = 'icons/turf/walls/wood_wall.dmi'; icon_state = "wood"; @@ -17650,7 +17650,7 @@ /turf/open/floor/wood, /area/syndicate_mothership) "Sj" = ( -/obj/machinery/vending/autodrobe/all_access{ +/obj/machinery/vending/autodrobe{ extended_inventory = 1 }, /obj/machinery/light, @@ -58771,7 +58771,7 @@ iX iX jm jr -iX +iF jr jK iX diff --git a/_maps/shuttles/emergency_gorilla.dmm b/_maps/shuttles/emergency_gorilla.dmm index 0c75cd8b7e..cc2e67ee3e 100644 --- a/_maps/shuttles/emergency_gorilla.dmm +++ b/_maps/shuttles/emergency_gorilla.dmm @@ -326,10 +326,6 @@ /mob/living/simple_animal/hostile/gorilla, /turf/open/floor/plasteel/shuttle, /area/shuttle/escape) -"bn" = ( -/obj/structure/reagent_dispensers/keg/semen, -/turf/open/floor/plating, -/area/shuttle/escape) "bo" = ( /obj/structure/closet/crate/freezer/surplus_limbs, /turf/open/floor/plasteel/shuttle, @@ -539,7 +535,7 @@ aD fV Pi bm -bn +ax bs bu "} @@ -610,7 +606,7 @@ aX aD fV bi -bn +ax bl fV ab diff --git a/_maps/shuttles/emergency_luxury.dmm b/_maps/shuttles/emergency_luxury.dmm index 2834f0c93f..a7faface75 100644 --- a/_maps/shuttles/emergency_luxury.dmm +++ b/_maps/shuttles/emergency_luxury.dmm @@ -422,7 +422,7 @@ /turf/open/floor/carpet/red, /area/shuttle/escape/luxury) "bD" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /turf/open/floor/carpet/red, /area/shuttle/escape/luxury) "bE" = ( diff --git a/_maps/shuttles/pirate_default.dmm b/_maps/shuttles/pirate_default.dmm index 9bd9d335c9..f664ea2c56 100644 --- a/_maps/shuttles/pirate_default.dmm +++ b/_maps/shuttles/pirate_default.dmm @@ -733,7 +733,7 @@ /turf/open/floor/plasteel, /area/shuttle/pirate) "bH" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /obj/effect/turf_decal/tile/bar, /obj/effect/turf_decal/tile/bar{ dir = 1 diff --git a/_maps/shuttles/whiteship_delta.dmm b/_maps/shuttles/whiteship_delta.dmm index 817f337503..84d2282c37 100644 --- a/_maps/shuttles/whiteship_delta.dmm +++ b/_maps/shuttles/whiteship_delta.dmm @@ -145,7 +145,7 @@ /turf/open/floor/plating, /area/shuttle/abandoned/crew) "ap" = ( -/obj/machinery/vending/boozeomat/all_access, +/obj/machinery/vending/boozeomat, /obj/effect/decal/cleanable/dirt{ desc = "A thin layer of dust coating the floor."; name = "dust" diff --git a/code/__DEFINES/MC.dm b/code/__DEFINES/MC.dm index 65be8258a1..bad64846d6 100644 --- a/code/__DEFINES/MC.dm +++ b/code/__DEFINES/MC.dm @@ -25,35 +25,38 @@ //SubSystem flags (Please design any new flags so that the default is off, to make adding flags to subsystems easier) //subsystem does not initialize. -#define SS_NO_INIT 1 +#define SS_NO_INIT (1<<0) //subsystem does not fire. // (like can_fire = 0, but keeps it from getting added to the processing subsystems list) // (Requires a MC restart to change) -#define SS_NO_FIRE 2 +#define SS_NO_FIRE (1<<1) //subsystem only runs on spare cpu (after all non-background subsystems have ran that tick) // SS_BACKGROUND has its own priority bracket -#define SS_BACKGROUND 4 +#define SS_BACKGROUND (1<<2) //subsystem does not tick check, and should not run unless there is enough time (or its running behind (unless background)) -#define SS_NO_TICK_CHECK 8 +#define SS_NO_TICK_CHECK (1<<3) //Treat wait as a tick count, not DS, run every wait ticks. // (also forces it to run first in the tick, above even SS_NO_TICK_CHECK subsystems) // (implies all runlevels because of how it works) // (overrides SS_BACKGROUND) // This is designed for basically anything that works as a mini-mc (like SStimer) -#define SS_TICKER 16 +#define SS_TICKER (1<<4) //keep the subsystem's timing on point by firing early if it fired late last fire because of lag // ie: if a 20ds subsystem fires say 5 ds late due to lag or what not, its next fire would be in 15ds, not 20ds. -#define SS_KEEP_TIMING 32 +#define SS_KEEP_TIMING (1<<5) //Calculate its next fire after its fired. // (IE: if a 5ds wait SS takes 2ds to run, its next fire should be 5ds away, not 3ds like it normally would be) // This flag overrides SS_KEEP_TIMING -#define SS_POST_FIRE_TIMING 64 +#define SS_POST_FIRE_TIMING (1<<6) + +/// Show in stat() by default even if SS_NO_FIRE +#define SS_ALWAYS_SHOW_STAT (1<<7) //SUBSYSTEM STATES #define SS_IDLE 0 //aint doing shit. diff --git a/code/__DEFINES/_flags/_flags.dm b/code/__DEFINES/_flags/_flags.dm index 396cf25be1..9facaf5d70 100644 --- a/code/__DEFINES/_flags/_flags.dm +++ b/code/__DEFINES/_flags/_flags.dm @@ -20,26 +20,41 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define DF_ISPROCESSING (1<<2) //FLAGS BITMASK - -#define HEAR_1 (1<<3) // This flag is what recursive_hear_check() uses to determine wether to add an item to the hearer list or not. -#define CHECK_RICOCHET_1 (1<<4) // Projectiels will check ricochet on things impacted that have this. -#define CONDUCT_1 (1<<5) // conducts electricity (metal etc.) -#define NODECONSTRUCT_1 (1<<7) // For machines and structures that should not break into parts, eg, holodeck stuff -#define OVERLAY_QUEUED_1 (1<<8) // atom queued to SSoverlay -#define ON_BORDER_1 (1<<9) // item has priority to check when entering or leaving -#define PREVENT_CLICK_UNDER_1 (1<<11) //Prevent clicking things below it on the same turf eg. doors/ fulltile windows +///This flag is what recursive_hear_check() uses to determine wether to add an item to the hearer list or not. +#define HEAR_1 (1<<3) +///Projectiels will check ricochet on things impacted that have this. +#define CHECK_RICOCHET_1 (1<<4) +///Conducts electricity (metal etc.). +#define CONDUCT_1 (1<<5) +///For machines and structures that should not break into parts, eg, holodeck stuff. +#define NODECONSTRUCT_1 (1<<7) +///Atom queued to SSoverlay. +#define OVERLAY_QUEUED_1 (1<<8) +///Item has priority to check when entering or leaving. +#define ON_BORDER_1 (1<<9) +///Prevent clicking things below it on the same turf eg. doors/ fulltile windows. +#define PREVENT_CLICK_UNDER_1 (1<<11) #define HOLOGRAM_1 (1<<12) -#define TESLA_IGNORE_1 (1<<13) // TESLA_IGNORE grants immunity from being targeted by tesla-style electricity -#define INITIALIZED_1 (1<<14) //Whether /atom/Initialize() has already run for the object -#define ADMIN_SPAWNED_1 (1<<15) //was this spawned by an admin? used for stat tracking stuff. -#define PREVENT_CONTENTS_EXPLOSION_1 (1<<16) /// should not get harmed if this gets caught by an explosion? +///Prevents mobs from getting chainshocked by teslas and the supermatter. +#define SHOCKED_1 (1<<13) +///Whether /atom/Initialize() has already run for the object. +#define INITIALIZED_1 (1<<14) +///was this spawned by an admin? used for stat tracking stuff. +#define ADMIN_SPAWNED_1 (1<<15) +/// should not get harmed if this gets caught by an explosion? +#define PREVENT_CONTENTS_EXPLOSION_1 (1<<16) +/// Early returns mob.face_atom() +#define BLOCK_FACE_ATOM_1 (1<<17) //turf-only flags #define NOJAUNT_1 (1<<0) #define UNUSED_RESERVATION_TURF_1 (1<<1) -#define CAN_BE_DIRTY_1 (1<<2) // If a turf can be made dirty at roundstart. This is also used in areas. -#define NO_LAVA_GEN_1 (1<<6) //Blocks lava rivers being generated on the turf -#define NO_RUINS_1 (1<<10) //Blocks ruins spawning on the turf +///If a turf can be made dirty at roundstart. This is also used in areas. +#define CAN_BE_DIRTY_1 (1<<2) +///Blocks lava rivers being generated on the turf. +#define NO_LAVA_GEN_1 (1<<6) +///Blocks ruins spawning on the turf. +#define NO_RUINS_1 (1<<10) /* These defines are used specifically with the atom/pass_flags bitmask @@ -75,14 +90,15 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define GOLIATH_WEAKNESS (1<<9) //CIT CHANGE //tesla_zap -#define TESLA_MACHINE_EXPLOSIVE (1<<0) -#define TESLA_ALLOW_DUPLICATES (1<<1) -#define TESLA_OBJ_DAMAGE (1<<2) -#define TESLA_MOB_DAMAGE (1<<3) -#define TESLA_MOB_STUN (1<<4) +#define ZAP_MACHINE_EXPLOSIVE (1<<0) +#define ZAP_ALLOW_DUPLICATES (1<<1) +#define ZAP_OBJ_DAMAGE (1<<2) +#define ZAP_MOB_DAMAGE (1<<3) +#define ZAP_MOB_STUN (1<<4) -#define TESLA_DEFAULT_FLAGS ALL -#define TESLA_FUSION_FLAGS TESLA_OBJ_DAMAGE | TESLA_MOB_DAMAGE | TESLA_MOB_STUN +#define ZAP_DEFAULT_FLAGS ALL +#define ZAP_FUSION_FLAGS ZAP_OBJ_DAMAGE | ZAP_MOB_DAMAGE | ZAP_MOB_STUN +#define ZAP_SUPERMATTER_FLAGS NONE //EMP protection #define EMP_PROTECT_SELF (1<<0) diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 0b46f21a97..e8e75c132a 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -83,10 +83,3 @@ #define SPAM_TRIGGER_WARNING 5 //Number of identical messages required before the spam-prevention will warn you to stfu #define SPAM_TRIGGER_AUTOMUTE 10 //Number of identical messages required before the spam-prevention will automute you - -///Max length of a keypress command before it's considered to be a forged packet/bogus command -#define MAX_KEYPRESS_COMMANDLENGTH 16 -///Max amount of keypress messages per second over two seconds before client is autokicked -#define MAX_KEYPRESS_AUTOKICK 100 -///Length of max held keys -#define MAX_HELD_KEYS 15 diff --git a/code/__DEFINES/admin/keybindings.dm b/code/__DEFINES/admin/keybindings.dm new file mode 100644 index 0000000000..3efc26c7d5 --- /dev/null +++ b/code/__DEFINES/admin/keybindings.dm @@ -0,0 +1,18 @@ +// Defines for managed input/keybinding system. +/// Max length of a keypress command before it's considered to be a forged packet/bogus command +#define MAX_KEYPRESS_COMMANDLENGTH 16 +/// Maximum keys that can be bound to one button +#define MAX_COMMANDS_PER_KEY 5 +/// Maximum keys per keybind +#define MAX_KEYS_PER_KEYBIND 3 +/// Max amount of keypress messages per second over two seconds before client is autokicked +#define MAX_KEYPRESS_AUTOKICK 100 +/// Max keys that can be held down at once by a client +#define MAX_HELD_KEYS 15 + +/// Macroset name of hotkeys/keybind only/modern mode +#define SKIN_MACROSET_HOTKEYS "hotkeys" +/// Macroset name of classic hotkey mode +#define SKIN_MACROSET_CLASSIC_HOTKEYS "oldhotkeys" +/// Macroset name of classic input mode +#define SKIN_MACROSET_CLASSIC_INPUT "oldinput" diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm index f9c3b0d427..2b19b557b2 100644 --- a/code/__DEFINES/atmospherics.dm +++ b/code/__DEFINES/atmospherics.dm @@ -298,6 +298,8 @@ GLOBAL_LIST_INIT(atmos_adjacent_savings, list(0,0)) #define ARCHIVE_TEMPERATURE(gas) gas.temperature_archived = gas.temperature +#define ARCHIVE(gas) gas.temperature_archived = gas.temperature; gas.gas_archive = gas.gases.Copy(); + GLOBAL_LIST_INIT(pipe_paint_colors, list( "amethyst" = rgb(130,43,255), //supplymain "blue" = rgb(0,0,255), diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index cc2cd8834a..3d15412efe 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -43,6 +43,7 @@ #define COLOR_RED_GRAY "#B4696A" #define COLOR_PALE_BLUE_GRAY "#98C5DF" #define COLOR_PALE_GREEN_GRAY "#B7D993" +#define COLOR_PALE_ORANGE "#FFC066" #define COLOR_PALE_RED_GRAY "#D59998" #define COLOR_PALE_PURPLE_GRAY "#CBB1CA" #define COLOR_PURPLE_GRAY "#AE8CA8" diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 8681246680..7c3d77f490 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -35,9 +35,9 @@ /// Default combat flags for those affected by ((stamina combat)) #define COMBAT_FLAGS_DEFAULT NONE /// Default combat flags for everyone else (so literally everyone but humans) -#define COMBAT_FLAGS_STAMSYSTEM_EXEMPT (COMBAT_FLAG_SPRINT_ACTIVE | COMBAT_FLAG_COMBAT_ACTIVE | COMBAT_FLAG_SPRINT_TOGGLED | COMBAT_FLAG_COMBAT_TOGGLED) +#define COMBAT_FLAGS_STAMSYSTEM_EXEMPT (COMBAT_FLAG_SPRINT_ACTIVE | COMBAT_FLAG_COMBAT_ACTIVE | COMBAT_FLAG_SPRINT_TOGGLED | COMBAT_FLAG_COMBAT_TOGGLED | COMBAT_FLAG_SPRINT_FORCED | COMBAT_FLAG_COMBAT_FORCED) /// Default combat flags for those only affected by sprint (so just silicons) -#define COMBAT_FLAGS_STAMEXEMPT_YESSPRINT (COMBAT_FLAG_COMBAT_ACTIVE | COMBAT_FLAG_COMBAT_TOGGLED) +#define COMBAT_FLAGS_STAMEXEMPT_YESSPRINT (COMBAT_FLAG_COMBAT_ACTIVE | COMBAT_FLAG_COMBAT_TOGGLED | COMBAT_FLAG_COMBAT_FORCED) /// The user wants combat mode on #define COMBAT_FLAG_COMBAT_TOGGLED (1<<0) @@ -57,6 +57,10 @@ #define COMBAT_FLAG_INTENTIONALLY_RESTING (1<<7) /// Currently stamcritted but not as violently #define COMBAT_FLAG_SOFT_STAMCRIT (1<<8) +/// Force combat mode on at all times, overrides everything including combat disable traits. +#define COMBAT_FLAG_COMBAT_FORCED (1<<9) +/// Force sprint mode on at all times, overrides everything including sprint disable traits. +#define COMBAT_FLAG_SPRINT_FORCED (1<<10) // Helpers for getting someone's stamcrit state. Cast to living. #define NOT_STAMCRIT 0 @@ -248,6 +252,15 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( #define TOTAL_MASS_MEDIEVAL_WEAPON 3.6 //very, very generic average sword/warpick/etc. weight in pounds. #define TOTAL_MASS_TOY_SWORD 1.5 +//stamina cost defines. +#define STAM_COST_ATTACK_OBJ_MULT 1.2 +#define STAM_COST_ATTACK_MOB_MULT 0.8 +#define STAM_COST_BATON_MOB_MULT 1 +#define STAM_COST_NO_COMBAT_MULT 1.25 +#define STAM_COST_W_CLASS_MULT 1.25 +#define STAM_COST_THROW_MULT 2 + + //bullet_act() return values #define BULLET_ACT_HIT "HIT" //It's a successful hit, whatever that means in the context of the thing it's hitting. #define BULLET_ACT_BLOCK "BLOCK" //It's a blocked hit, whatever that means in the context of the thing it's hitting. diff --git a/code/__DEFINES/combat/block.dm b/code/__DEFINES/combat/block.dm index 84b739a1c7..19c541826e 100644 --- a/code/__DEFINES/combat/block.dm +++ b/code/__DEFINES/combat/block.dm @@ -1,3 +1,13 @@ +/// Check whether or not we can block, without "triggering" a block. Basically run checks without effects like depleting shields. +/// Wrapper for do_run_block(). The arguments on that means the same as for this. +#define mob_check_block(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)\ + do_run_block(FALSE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list) + +/// Runs a block "sequence", effectively checking and then doing effects if necessary. +/// Wrapper for do_run_block(). The arguments on that means the same as for this. +#define mob_run_block(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)\ + do_run_block(TRUE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list) + // Don't ask why there's block_parry.dm and this. This is for the run_block() system, which is the "parent" system of the directional block and parry systems. /// Bitflags for check_block() and handle_block(). Meant to be combined. You can be hit and still reflect, for example, if you do not use BLOCK_SUCCESS. diff --git a/code/__DEFINES/construction.dm b/code/__DEFINES/construction.dm index 77ec97f47e..65e1d0e980 100644 --- a/code/__DEFINES/construction.dm +++ b/code/__DEFINES/construction.dm @@ -103,4 +103,9 @@ #define RCD_COMPUTER 16 #define RCD_UPGRADE_FRAMES 1 -#define RCD_UPGRADE_SIMPLE_CIRCUITS 2 \ No newline at end of file +#define RCD_UPGRADE_SIMPLE_CIRCUITS 2 + +//Electrochromatic window defines. +#define NOT_ELECTROCHROMATIC 0 +#define ELECTROCHROMATIC_OFF 1 +#define ELECTROCHROMATIC_DIMMED 2 diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index ce4505265f..6c68e7ecad 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -89,7 +89,7 @@ #define COMSIG_EXIT_AREA "exit_area" //from base of area/Exited(): (/area) #define COMSIG_CLICK "atom_click" //from base of atom/Click(): (location, control, params, mob/user) -#define COMSIG_CLICK_SHIFT "shift_click" //from base of atom/ShiftClick(): (/mob) +#define COMSIG_CLICK_SHIFT "shift_click" //from base of atom/ShiftClick(): (/mob), return flags also used by other signals. #define COMPONENT_ALLOW_EXAMINATE 1 #define COMPONENT_DENY_EXAMINATE 2 //Higher priority compared to the above one @@ -141,13 +141,17 @@ #define HEARING_SOURCE 8*/ #define COMSIG_MOVABLE_DISPOSING "movable_disposing" //called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source) #define COMSIG_MOVABLE_TELEPORTED "movable_teleported" //from base of do_teleport(): (channel, turf/origin, turf/destination) + // /mind signals #define COMSIG_PRE_MIND_TRANSFER "pre_mind_transfer" //from base of mind/transfer_to() before it's done: (new_character, old_character) #define COMPONENT_STOP_MIND_TRANSFER 1 //stops the mind transfer from happening. #define COMSIG_MIND_TRANSFER "mind_transfer" //from base of mind/transfer_to() when it's done: (new_character, old_character) // /mob signals -#define COMSIG_MOB_EXAMINATE "mob_examinate" //from base of /mob/verb/examinate(): (atom/A) +#define COMSIG_MOB_CLICKED_SHIFT_ON "mob_shift_click_on" //from base of /atom/ShiftClick(): (atom/A), for return values, see COMSIG_CLICK_SHIFT +#define COMSIG_MOB_FOV_VIEW "mob_visible_atoms" //from base of mob/fov_view(): (list/visible_atoms) +#define COMSIG_MOB_EXAMINATE "mob_examinate" //from base of /mob/verb/examinate(): (atom/A), for return values, see COMSIG_CLICK_SHIFT + #define COMPONENT_EXAMINATE_BLIND 3 //outputs the "something is there but you can't see it" message. #define COMSIG_MOB_DEATH "mob_death" //from base of mob/death(): (gibbed) #define COMPONENT_BLOCK_DEATH_BROADCAST 1 //stops the death from being broadcasted in deadchat. #define COMSIG_MOB_CLICKON "mob_clickon" //from base of mob/clickon(): (atom/A, params) @@ -181,9 +185,14 @@ #define SPEECH_LANGUAGE 5 // #define SPEECH_IGNORE_SPAM 6 // #define SPEECH_FORCED 7 +#define COMSIG_MOB_FOV_VIEWER "mob_is_viewer" //from base of /fov_viewers(): (atom/center, depth, viewers_list) +#define COMSIG_MOB_GET_VISIBLE_MESSAGE "mob_get_visible_message" //from base of atom/visible_message(): (atom/A, msg, range, ignored_mobs) + #define COMPONENT_NO_VISIBLE_MESSAGE 1 //exactly what's said on the tin. #define COMSIG_MOB_ANTAG_ON_GAIN "mob_antag_on_gain" //from base of /datum/antagonist/on_gain(): (antag_datum) -#define COMSIG_MOB_SPELL_CAN_CAST "mob_spell_can_cast" //called from base of /obj/effect/proc_holder/spell/can_cast(): (spell) +#define COMSIG_MOB_SPELL_CAN_CAST "mob_spell_can_cast" //from base of /obj/effect/proc_holder/spell/can_cast(): (spell) + +#define COMSIG_ROBOT_UPDATE_ICONS "robot_update_icons" //from base of robot/update_icons(): () // /mob/living signals #define COMSIG_LIVING_REGENERATE_LIMBS "living_regenerate_limbs" //from base of /mob/living/regenerate_limbs(): (noheal, excluded_limbs) @@ -191,11 +200,16 @@ #define COMSIG_LIVING_IGNITED "living_ignite" //from base of mob/living/IgniteMob() (/mob/living) #define COMSIG_LIVING_EXTINGUISHED "living_extinguished" //from base of mob/living/ExtinguishMob() (/mob/living) #define COMSIG_LIVING_ELECTROCUTE_ACT "living_electrocute_act" //from base of mob/living/electrocute_act(): (shock_damage, source, siemens_coeff, flags) +#define COMSIG_LIVING_SHOCK_PREVENTED "living_shock_prevented" //sent when items with siemen coeff. of 0 block a shock: (power_source, source, siemens_coeff, dist_check) #define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock" //sent by stuff like stunbatons and tasers: () #define COMSIG_LIVING_REVIVE "living_revive" //from base of mob/living/revive() (full_heal, admin_revive) -#define COMSIG_MOB_CLIENT_LOGIN "comsig_mob_client_login" //sent when a mob/login() finishes: (client) -#define COMSIG_MOB_CLIENT_LOGOUT "comsig_mob_client_logout" //sent when a mob/logout() starts: (client) -#define COMSIG_MOB_CLIENT_MOVE "comsig_mob_client_move" //sent when client/Move() finishes with no early returns: (client, direction, n, oldloc) + +#define COMSIG_MOB_CLIENT_LOGIN "mob_client_login" //sent when a mob/login() finishes: (client) +#define COMSIG_MOB_CLIENT_LOGOUT "mob_client_logout" //sent when a mob/logout() starts: (client) +#define COMSIG_MOB_CLIENT_MOVE "mob_client_move" //sent when client/Move() finishes with no early returns: (client, direction, n, oldloc) +#define COMSIG_MOB_CLIENT_CHANGE_VIEW "mob_client_change_view" //from base of /client/change_view(): (client, old_view, view) + +#define COMSIG_MOB_RESET_PERSPECTIVE "mob_reset_perspective" //from base of /mob/reset_perspective(): (atom/target) #define COMSIG_LIVING_GUN_PROCESS_FIRE "living_gun_process_fire" //from base of /obj/item/gun/proc/process_fire(): (atom/target, params, zone_override) // This returns flags as defined for block in __DEFINES/combat.dm! #define COMSIG_LIVING_RUN_BLOCK "living_do_run_block" //from base of mob/living/do_run_block(): (real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone) @@ -256,6 +270,9 @@ // THE FOLLOWING TWO BLOCKS SHOULD RETURN BLOCK FLAGS AS DEFINED IN __DEFINES/combat.dm! #define COMSIG_ITEM_CHECK_BLOCK "check_block" //from base of obj/item/check_block(): (mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) #define COMSIG_ITEM_RUN_BLOCK "run_block" //from base of obj/item/run_block(): (mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) +// Item mouse siganls +#define COMSIG_ITEM_MOUSE_EXIT "item_mouse_exit" //from base of obj/item/MouseExited(): (location, control, params) +#define COMSIG_ITEM_MOUSE_ENTER "item_mouse_enter" //from base of obj/item/MouseEntered(): (location, control, params) #define COMSIG_ITEM_DECONSTRUCTOR_DEEPSCAN "deconstructor_deepscan" //Called by deconstructive analyzers deepscanning an item: (obj/machinery/rnd/destructive_analyzer/analyzer_machine, mob/user, list/information_list) // Uncovered information #define COMPONENT_DEEPSCAN_UNCOVERED_INFORMATION 1 @@ -302,6 +319,9 @@ #define COMSIG_SPECIES_GAIN "species_gain" //from datum/species/on_species_gain(): (datum/species/new_species, datum/species/old_species) #define COMSIG_SPECIES_LOSS "species_loss" //from datum/species/on_species_loss(): (datum/species/lost_species) +// /datum/mutation signals +#define COMSIG_HUMAN_MUTATION_LOSS "human_mutation_loss" //from datum/mutation/human/on_losing(): (datum/mutation/human/lost_mutation) + /*******Component Specific Signals*******/ //Janitor #define COMSIG_TURF_IS_WET "check_turf_wet" //(): Returns bitflags of wet values. diff --git a/code/__DEFINES/economy.dm b/code/__DEFINES/economy.dm new file mode 100644 index 0000000000..bc9534f527 --- /dev/null +++ b/code/__DEFINES/economy.dm @@ -0,0 +1,35 @@ +#define STARTING_PAYCHECKS 5 + +#define PAYCHECK_ASSISTANT 25 +#define PAYCHECK_MINIMAL 75 +#define PAYCHECK_EASY 125 +#define PAYCHECK_MEDIUM 175 +#define PAYCHECK_HARD 200 +#define PAYCHECK_COMMAND 250 + +#define MAX_GRANT_CIV 2500 +#define MAX_GRANT_ENG 3000 +#define MAX_GRANT_SCI 5000 +#define MAX_GRANT_SECMEDSRV 3000 + +#define ACCOUNT_CIV "CIV" +#define ACCOUNT_CIV_NAME "Civil Budget" +#define ACCOUNT_ENG "ENG" +#define ACCOUNT_ENG_NAME "Engineering Budget" +#define ACCOUNT_SCI "SCI" +#define ACCOUNT_SCI_NAME "Scientific Budget" +#define ACCOUNT_MED "MED" +#define ACCOUNT_MED_NAME "Medical Budget" +#define ACCOUNT_SRV "SRV" +#define ACCOUNT_SRV_NAME "Service Budget" +#define ACCOUNT_CAR "CAR" +#define ACCOUNT_CAR_NAME "Cargo Budget" +#define ACCOUNT_SEC "SEC" +#define ACCOUNT_SEC_NAME "Defense Budget" + +#define NO_FREEBIES "commies go home" + +//ID bank account support defines. +#define ID_NO_BANK_ACCOUNT 0 +#define ID_FREE_BANK_ACCOUNT 1 +#define ID_LOCKED_BANK_ACCOUNT 2 diff --git a/code/__DEFINES/footsteps.dm b/code/__DEFINES/footsteps.dm index 16d763606b..5acda2274c 100644 --- a/code/__DEFINES/footsteps.dm +++ b/code/__DEFINES/footsteps.dm @@ -24,6 +24,15 @@ #define FOOTPRINT_SNAKE "snake" #define FOOTPRINT_DRAG "drag" +//footstep mob defines +#define FOOTSTEP_MOB_CLAW 1 +#define FOOTSTEP_MOB_BAREFOOT 2 +#define FOOTSTEP_MOB_HEAVY 3 +#define FOOTSTEP_MOB_SHOE 4 +#define FOOTSTEP_MOB_HUMAN 5 //Warning: Only works on /mob/living/carbon/human +#define FOOTSTEP_MOB_SLIME 6 +#define FOOTSTEP_MOB_CRAWL 7 + /* id = list( diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 122ba67402..28ec3383ae 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -148,50 +148,6 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define isclown(A) (istype(A, /mob/living/simple_animal/hostile/retaliate/clown)) -GLOBAL_LIST_INIT(shoefootmob, typecacheof(list( - /mob/living/carbon/human/, - /mob/living/simple_animal/cow, - /mob/living/simple_animal/hostile/cat_butcherer, - /mob/living/simple_animal/hostile/faithless, - /mob/living/simple_animal/hostile/nanotrasen, - /mob/living/simple_animal/hostile/pirate, - /mob/living/simple_animal/hostile/russian, - /mob/living/simple_animal/hostile/syndicate, - /mob/living/simple_animal/hostile/wizard, - /mob/living/simple_animal/hostile/zombie, - /mob/living/simple_animal/hostile/retaliate/clown, - /mob/living/simple_animal/hostile/retaliate/spaceman, - /mob/living/simple_animal/hostile/retaliate/nanotrasenpeace, - /mob/living/simple_animal/hostile/retaliate/goat, - /mob/living/carbon/true_devil, - ))) - -GLOBAL_LIST_INIT(clawfootmob, typecacheof(list( - /mob/living/carbon/alien/humanoid, - /mob/living/simple_animal/hostile/alien, - /mob/living/simple_animal/pet/cat, - /mob/living/simple_animal/pet/dog, - /mob/living/simple_animal/pet/fox, - /mob/living/simple_animal/chicken, - /mob/living/simple_animal/hostile/bear, - /mob/living/simple_animal/hostile/jungle/mega_arachnid, - /mob/living/simple_animal/hostile/asteroid/ice_whelp, - /mob/living/simple_animal/hostile/asteroid/wolf, - /mob/living/simple_animal/hostile/asteroid/polarbear - ))) - -GLOBAL_LIST_INIT(barefootmob, typecacheof(list( - /mob/living/carbon/monkey, - /mob/living/simple_animal/pet/penguin, - /mob/living/simple_animal/hostile/gorilla, - /mob/living/simple_animal/hostile/jungle/mook - ))) - -GLOBAL_LIST_INIT(heavyfootmob, typecacheof(list( - /mob/living/simple_animal/hostile/megafauna, - /mob/living/simple_animal/hostile/jungle/leaper - ))) - //Misc mobs #define isobserver(A) (istype(A, /mob/dead/observer)) diff --git a/code/__DEFINES/language.dm b/code/__DEFINES/language.dm index dc2ac19e65..add4a8e277 100644 --- a/code/__DEFINES/language.dm +++ b/code/__DEFINES/language.dm @@ -3,5 +3,24 @@ #define LANGUAGE_HIDE_ICON_IF_UNDERSTOOD 4 #define LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD 8 -#define LANGUAGE_KNOWN "language_known" -#define LANGUAGE_SHADOWED "language_shadowed" +// LANGUAGE SOURCE DEFINES +#define LANGUAGE_ALL "all" // For use in full removal only. +#define LANGUAGE_ATOM "atom" +#define LANGUAGE_MIND "mind" + +#define LANGUAGE_ABSORB "absorb" +#define LANGUAGE_APHASIA "aphasia" +#define LANGUAGE_BLOODSUCKER "bloodsucker" +#define LANGUAGE_CLOCKIE "clockie" +#define LANGUAGE_CULTIST "cultist" +#define LANGUAGE_CURATOR "curator" +#define LANGUAGE_DEVIL "devil" +#define LANGUAGE_GLAND "gland" +#define LANGUAGE_HAT "hat" +#define LANGUAGE_HIGH "high" +#define LANGUAGE_MALF "malf" +#define LANGUAGE_MASTER "master" +#define LANGUAGE_SOFTWARE "software" +#define LANGUAGE_STONER "stoner" +#define LANGUAGE_VASSAL "vassal" +#define LANGUAGE_VOICECHANGE "voicechange" diff --git a/code/__DEFINES/layers_planes.dm b/code/__DEFINES/layers_planes.dm index a6c31bf965..6f33bb1a0e 100644 --- a/code/__DEFINES/layers_planes.dm +++ b/code/__DEFINES/layers_planes.dm @@ -11,16 +11,38 @@ #define PLANE_SPACE_PARALLAX_RENDER_TARGET "PLANE_SPACE_PARALLAX" #define OPENSPACE_LAYER 17 //Openspace layer over all -#define OPENSPACE_PLANE -4 //Openspace plane below all turfs -#define OPENSPACE_BACKDROP_PLANE -3 //Black square just over openspace plane to guaranteed cover all in openspace turf +#define OPENSPACE_PLANE -10 //Openspace plane below all turfs +#define OPENSPACE_BACKDROP_PLANE -9 //Black square just over openspace plane to guaranteed cover all in openspace turf -#define FLOOR_PLANE -2 +#define FLOOR_PLANE -8 #define FLOOR_PLANE_RENDER_TARGET "FLOOR_PLANE" -#define GAME_PLANE -1 + +#define WALL_PLANE -7 +#define WALL_PLANE_RENDER_TARGET "WALL_PLANE" + +#define ABOVE_WALL_PLANE -6 +#define ABOVE_WALL_PLANE_RENDER_TARGET "ABOVE_WALL_PLANE" + +#define FIELD_OF_VISION_BLOCKER_PLANE -5 +#define FIELD_OF_VISION_BLOCKER_RENDER_TARGET "*FIELD_OF_VISION_BLOCKER_PLANE" + +#define FIELD_OF_VISION_PLANE -4 +#define FIELD_OF_VISION_RENDER_TARGET "*FIELD_OF_VISION_PLANE" +#define FIELD_OF_VISION_LAYER 17 //used to place the visual (not the mask) shadow cone above any other floor plane stuff. + +#define GAME_PLANE -3 #define GAME_PLANE_RENDER_TARGET "GAME_PLANE" + +#define FIELD_OF_VISION_VISUAL_PLANE -2 //Yea, FoV does require quite a few planes to work with 513 filters to a decent degree. +#define FIELD_OF_VISION_VISUAL_RENDER_TARGET "FIELD_OF_VISION_VISUAL_PLANE" + +#define CHAT_PLANE -1 //We don't want heard messages to be hidden by FoV. +#define CHAT_LAYER 12.1 //Legacy, it doesn't matter that much because we are displayed above the game plane anyway. + #define BLACKNESS_PLANE 0 //To keep from conflicts with SEE_BLACKNESS internals #define BLACKNESS_PLANE_RENDER_TARGET "BLACKNESS_PLANE" +///Layers most often used by atoms of plane lower than GAME_PLANE #define SPACE_LAYER 1.8 //#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define #define MID_TURF_LAYER 2.02 @@ -40,11 +62,12 @@ #define GAS_PIPE_VISIBLE_LAYER 2.47 #define GAS_FILTER_LAYER 2.48 #define GAS_PUMP_LAYER 2.49 + #define LOW_OBJ_LAYER 2.5 #define LOW_SIGIL_LAYER 2.52 #define SIGIL_LAYER 2.54 #define HIGH_SIGIL_LAYER 2.56 - +///Layers most often used by atoms of plane equal or higher than GAME_PLANE #define BELOW_OPEN_DOOR_LAYER 2.6 #define BLASTDOOR_LAYER 2.65 #define OPEN_DOOR_LAYER 2.7 @@ -80,8 +103,9 @@ #define SPACEVINE_LAYER 4.8 #define SPACEVINE_MOB_LAYER 4.9 //#define FLY_LAYER 5 //For easy recordkeeping; this is a byond define -#define GASFIRE_LAYER 5.05 -#define RIPPLE_LAYER 5.1 +#define ABOVE_FLY_LAYER 5.1 +#define GASFIRE_LAYER 5.2 +#define RIPPLE_LAYER 5.3 #define GHOST_LAYER 6 #define LOW_LANDMARK_LAYER 9 @@ -91,8 +115,6 @@ #define MASSIVE_OBJ_LAYER 11 #define POINT_LAYER 12 -#define CHAT_LAYER 12.1 - #define EMISSIVE_BLOCKER_PLANE 12 #define EMISSIVE_BLOCKER_LAYER 12 #define EMISSIVE_BLOCKER_RENDER_TARGET "*EMISSIVE_BLOCKER_PLANE" @@ -136,19 +158,20 @@ #define HUD_LAYER 21 #define HUD_RENDER_TARGET "HUD_PLANE" -#define VOLUMETRIC_STORAGE_BOX_PLANE 23 -#define VOLUMETRIC_STORAGE_BOX_LAYER 23 +#define VOLUMETRIC_STORAGE_BOX_PLANE 22 +#define VOLUMETRIC_STORAGE_BOX_LAYER 22 #define VOLUMETRIC_STORAGE_BOX_RENDER_TARGET "VOLUME_STORAGE_BOX_PLANE" -#define VOLUMETRIC_STORAGE_ITEM_PLANE 24 -#define VOLUMETRIC_STORAGE_ITEM_LAYER 24 +#define VOLUMETRIC_STORAGE_ITEM_PLANE 23 +#define VOLUMETRIC_STORAGE_ITEM_LAYER 23 +#define VOLUMETRIC_STORAGE_ACTIVE_ITEM_LAYER 25 +#define VOLUMETRIC_STORAGE_ACTIVE_ITEM_PLANE 25 #define VOLUMETRIC_STORAGE_ITEM_RENDER_TARGET "VOLUME_STORAGE_ITEM_PLANE" -#define ABOVE_HUD_PLANE 25 -#define ABOVE_HUD_LAYER 25 +#define ABOVE_HUD_PLANE 30 +#define ABOVE_HUD_LAYER 30 #define ABOVE_HUD_RENDER_TARGET "ABOVE_HUD_PLANE" -#define SPLASHSCREEN_LAYER 30 -#define SPLASHSCREEN_PLANE 30 +#define SPLASHSCREEN_LAYER 90 +#define SPLASHSCREEN_PLANE 90 #define SPLASHSCREEN_RENDER_TARGET "SPLASHSCREEN_PLANE" - diff --git a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm index 9693d46d00..7e1559cede 100644 --- a/code/__DEFINES/logging.dm +++ b/code/__DEFINES/logging.dm @@ -18,6 +18,7 @@ #define INVESTIGATE_CIRCUIT "circuit" #define INVESTIGATE_FERMICHEM "fermichem" #define INVESTIGATE_RCD "rcd" +#define INVESTIGATE_CRYOGENICS "cryogenics" // Logging types for log_message() #define LOG_ATTACK (1 << 0) diff --git a/code/__DEFINES/maps.dm b/code/__DEFINES/maps.dm index 47546cac30..c5c2dd58c2 100644 --- a/code/__DEFINES/maps.dm +++ b/code/__DEFINES/maps.dm @@ -41,6 +41,7 @@ require only minor tweaks. #define ZTRAIT_ICE_RUINS "Ice Ruins" #define ZTRAIT_ICE_RUINS_UNDERGROUND "Ice Ruins Underground" #define ZTRAIT_ISOLATED_RUINS "Isolated Ruins" //Placing ruins on z levels with this trait will use turf reservation instead of usual placement. +#define ZTRAIT_VIRTUAL_REALITY "Virtual Reality" //boolean - weather types that occur on the level #define ZTRAIT_SNOWSTORM "Weather_Snowstorm" @@ -80,6 +81,7 @@ require only minor tweaks. ZTRAIT_BOMBCAP_MULTIPLIER = 5, \ ZTRAIT_BASETURF = /turf/open/lava/smooth/lava_land_surface) #define ZTRAITS_REEBE list(ZTRAIT_REEBE = TRUE, ZTRAIT_BOMBCAP_MULTIPLIER = 0.5) +#define ZTRAITS_VR list(ZTRAIT_VIRTUAL_REALITY = TRUE, ZTRAIT_AWAY = TRUE) #define DL_NAME "name" #define DL_TRAITS "traits" diff --git a/code/__DEFINES/maths.dm b/code/__DEFINES/maths.dm index e418b8b4c6..24726b8058 100644 --- a/code/__DEFINES/maths.dm +++ b/code/__DEFINES/maths.dm @@ -209,3 +209,5 @@ /// Make sure something is a boolean TRUE/FALSE 1/0 value, since things like bitfield & bitflag doesn't always give 1s and 0s. #define FORCE_BOOLEAN(x) ((x)? TRUE : FALSE) + +#define TILES_TO_PIXELS(tiles) (tiles * PIXELS) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 42095aba41..9847556b37 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -9,6 +9,9 @@ #define TEXT_EAST "[EAST]" #define TEXT_WEST "[WEST]" +/// world.icon_size +#define PIXELS 32 + //These get to go at the top, because they're special //You can use these defines to get the typepath of the currently running proc/verb (yes procs + verbs are objects) /* eg: @@ -463,7 +466,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define PDAIMG(what) {""} //Filters -#define AMBIENT_OCCLUSION list("type"="drop_shadow","x"=0,"y"=-2,"size"=4,"color"="#04080FAA") +#define AMBIENT_OCCLUSION(_size, _color) list("type"="drop_shadow","x"=0,"y"=-2,"size"=_size,"color"=_color) #define EYE_BLUR(size) list("type"="blur", "size"=size) #define GRAVITY_MOTION_BLUR list("type"="motion_blur","x"=0,"y"=0) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 17aff463dc..29ab67271c 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -138,6 +138,7 @@ #define MOOD_LEVEL_SAD4 -25 //Sanity levels for humans +#define SANITY_AMAZING 150 #define SANITY_GREAT 125 #define SANITY_NEUTRAL 100 #define SANITY_DISTURBED 75 @@ -289,8 +290,15 @@ #define HUMAN_FIRE_STACK_ICON_NUM 3 +#define TYPING_INDICATOR_TIMEOUT 5 MINUTES + #define GRAB_PIXEL_SHIFT_PASSIVE 6 #define GRAB_PIXEL_SHIFT_AGGRESSIVE 12 #define GRAB_PIXEL_SHIFT_NECK 16 #define SLEEP_CHECK_DEATH(X) sleep(X); if(QDELETED(src) || stat == DEAD) return; + +/// Field of vision defines. +#define FOV_90_DEGREES 90 +#define FOV_180_DEGREES 180 +#define FOV_270_DEGREES 270 diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index 06926317ee..84eed5483a 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -30,8 +30,9 @@ #define CHAT_GHOSTPDA (1<<8) #define CHAT_GHOSTRADIO (1<<9) #define CHAT_LOOC (1<<10) +#define CHAT_BANKCARD (1<<11) -#define TOGGLES_DEFAULT_CHAT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_PULLR|CHAT_GHOSTWHISPER|CHAT_GHOSTPDA|CHAT_GHOSTRADIO|CHAT_LOOC) +#define TOGGLES_DEFAULT_CHAT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_PULLR|CHAT_GHOSTWHISPER|CHAT_GHOSTPDA|CHAT_GHOSTRADIO|CHAT_LOOC|CHAT_BANKCARD) #define PARALLAX_INSANE -1 //for show offs #define PARALLAX_HIGH 0 //default. diff --git a/code/__DEFINES/profile.dm b/code/__DEFINES/profile.dm index 8929e0f05e..5fc8478901 100644 --- a/code/__DEFINES/profile.dm +++ b/code/__DEFINES/profile.dm @@ -26,4 +26,4 @@ #define PROFILE_ITEM_LEN 2 #define PROFILE_ITEM_TIME 1 -#define PROFILE_ITEM_COUNT 2 \ No newline at end of file +#define PROFILE_ITEM_COUNT 2 diff --git a/code/__DEFINES/robots.dm b/code/__DEFINES/robots.dm index affa23d30a..09cea91540 100644 --- a/code/__DEFINES/robots.dm +++ b/code/__DEFINES/robots.dm @@ -51,6 +51,19 @@ #define ASSEMBLY_FOURTH_STEP 3 #define ASSEMBLY_FIFTH_STEP 4 +//Bot Upgrade defines +#define UPGRADE_CLEANER_ADVANCED_MOP (1<<0) +#define UPGRADE_CLEANER_BROOM (1<<1) + +#define UPGRADE_MEDICAL_HYPOSPRAY (1<<0) +#define UPGRADE_MEDICAL_CHEM_BOARD (1<<1) +#define UPGRADE_MEDICAL_CRYO_BOARD (1<<2) +#define UPGRADE_MEDICAL_CHEM_MASTER (1<<3) +#define UPGRADE_MEDICAL_SLEEP_BOARD (1<<4) +#define UPGRADE_MEDICAL_PIERERCING (1<<5) + +#define UPGRADE_FLOOR_ARTBOX (1<<0) +#define UPGRADE_FLOOR_SYNDIBOX (1<<1) //Checks to determine borg availability depending on the server's config. These are defines in the interest of reducing copypasta #define BORG_SEC_AVAILABLE (!CONFIG_GET(flag/disable_secborg) && GLOB.security_level >= CONFIG_GET(number/minimum_secborg_alert)) diff --git a/code/__DEFINES/rust_g.config.dm b/code/__DEFINES/rust_g.config.dm deleted file mode 100644 index 68a1b42fb1..0000000000 --- a/code/__DEFINES/rust_g.config.dm +++ /dev/null @@ -1 +0,0 @@ -#define RUSTG_OVERRIDE_BUILTINS \ No newline at end of file diff --git a/code/__DEFINES/rust_g.dm b/code/__DEFINES/rust_g.dm index ccd5b92c79..aeacdb7c51 100644 --- a/code/__DEFINES/rust_g.dm +++ b/code/__DEFINES/rust_g.dm @@ -1,10 +1,27 @@ // rust_g.dm - DM API for rust_g extension library #define RUST_G "rust_g" +#define RUSTG_JOB_NO_RESULTS_YET "NO RESULTS YET" +#define RUSTG_JOB_NO_SUCH_JOB "NO SUCH JOB" +#define RUSTG_JOB_ERROR "JOB PANICKED" + #define rustg_dmi_strip_metadata(fname) call(RUST_G, "dmi_strip_metadata")(fname) +#define rustg_dmi_create_png(fname,width,height,data) call(RUST_G, "dmi_create_png")(fname,width,height,data) #define rustg_git_revparse(rev) call(RUST_G, "rg_git_revparse")(rev) #define rustg_git_commit_date(rev) call(RUST_G, "rg_git_commit_date")(rev) -#define rustg_log_write(fname, text) call(RUST_G, "log_write")(fname, text) +#define rustg_log_write(fname, text, format) call(RUST_G, "log_write")(fname, text, format) /proc/rustg_log_close_all() return call(RUST_G, "log_close_all")() + +// RUST-G defines & procs for HTTP component +#define RUSTG_HTTP_METHOD_GET "get" +#define RUSTG_HTTP_METHOD_POST "post" +#define RUSTG_HTTP_METHOD_PUT "put" +#define RUSTG_HTTP_METHOD_DELETE "delete" +#define RUSTG_HTTP_METHOD_PATCH "patch" +#define RUSTG_HTTP_METHOD_HEAD "head" + +#define rustg_http_request_blocking(method, url, body, headers) call(RUST_G, "http_request_blocking")(method, url, body, headers) +#define rustg_http_request_async(method, url, body, headers) call(RUST_G, "http_request_async")(method, url, body, headers) +#define rustg_http_check_request(req_id) call(RUST_G, "http_check_request")(req_id) diff --git a/code/__DEFINES/skills/defines.dm b/code/__DEFINES/skills/defines.dm new file mode 100644 index 0000000000..659c0fe11b --- /dev/null +++ b/code/__DEFINES/skills/defines.dm @@ -0,0 +1,103 @@ + +/// true/false +#define SKILL_PROGRESSION_BINARY 1 +/// numerical +#define SKILL_PROGRESSION_NUMERICAL 2 +/// Enum +#define SKILL_PROGRESSION_ENUM 3 +/// Levels +#define SKILL_PROGRESSION_LEVEL 4 + + +/// Max value of skill for numerical skills +#define SKILL_NUMERICAL_MAX 100 +/// Min value of skill for numerical skills +#define SKILL_NUMERICAL_MIN 0 + +// Standard values for job starting skills + +#define STARTING_SKILL_SURGERY_MEDICAL 35 //out of SKILL_NUMERICAL_MAX + +// Standard values for job starting skill affinities + +#define STARTING_SKILL_AFFINITY_DEF_JOB 1.2 + +// Standard values for skill gain (this is multiplied by affinity) + +#define DEF_SKILL_GAIN 1 +#define SKILL_GAIN_SURGERY_PER_STEP 0.25 + +//An extra point for each few seconds of delay when using a tool. Before the multiplier. +#define SKILL_GAIN_DELAY_DIVISOR 3 SECONDS + +///Items skill_traits and other defines +#define SKILL_USE_TOOL "use_tool" +#define SKILL_TRAINING_TOOL "training_tool" +#define SKILL_ATTACK_MOB "attack_mob" +#define SKILL_TRAIN_ATTACK_MOB "train_attack_mob" +#define SKILL_ATTACK_OBJ "attack_obj" +#define SKILL_TRAIN_ATTACK_OBJ "train_attack_obj" +#define SKILL_STAMINA_COST "stamina_cost" //Influences the stamina cost from weapon usage. +#define SKILL_THROW_STAM_COST "throw_stam_cost" +#define SKILL_COMBAT_MODE "combat_mode" //The user must have combat mode on. +#define SKILL_SANITY "sanity" //Is the skill affected by (in)sanity. +#define SKILL_INTELLIGENCE "intelligence" //Is the skill affected by brain damage? + +///competency_threshold defines +#define THRESHOLD_UNTRAINED "untrained" +#define THRESHOLD_COMPETENT "competent" +#define THRESHOLD_EXPERT "expert" +#define THRESHOLD_MASTER "master" + +/// Level/Experience skills defines. +#define STD_XP_LVL_UP 100 +#define STD_XP_LVL_MULTI 2 +#define STD_MAX_LVL 4 + +#define RPG_MAX_LVL 100 + +#define DORF_XP_LVL_UP 400 +#define DORF_XP_LVL_MULTI 100 +#define DORF_MAX_LVL 20 // Dabbling, novice, adequate, [...], legendary +3, legendary +4, legendary +5 + +//level up methods defines +#define STANDARD_LEVEL_UP "standard_level_up" +#define DWARFY_LEVEL_UP "dwarfy_level_up" + +//job skill level defines +#define JOB_SKILL_UNTRAINED 0 +#define JOB_SKILL_BASIC 1 +#define JOB_SKILL_TRAINED 2 +#define JOB_SKILL_EXPERT 3 +#define JOB_SKILL_MASTER 4 + +//other skill level defines, not an exhaustive catalogue, only contains be most relevant ones. +#define DORF_SKILL_COMPETENT 3 +#define DORF_SKILL_EXPERT 8 +#define DORF_SKILL_MASTER 12 + +/// Skill modifier defines and flags. +#define MODIFIER_SKILL_VALUE (1<<0) +#define MODIFIER_SKILL_AFFINITY (1<<1) +#define MODIFIER_SKILL_LEVEL (1<<2) +///makes the skill modifier a multiplier, not an addendum. +#define MODIFIER_SKILL_MULT (1<<3) +///Sets the skill to the defined value if lower than that. Highly reccomended you don't use it with MODIFIER_SKILL_MULT. +#define MODIFIER_SKILL_VIRTUE (1<<4) +///Does the opposite of the above. combining both effectively results in the skill being locked to the specified value. +#define MODIFIER_SKILL_HANDICAP (1<<5) +///Makes it untransferred by mind.transfer_to() +#define MODIFIER_SKILL_BODYBOUND (1<<6) +///Adds the difference of the current value and the value stored at the time the modifier was added to the result. +#define MODIFIER_SKILL_ORIGIN_DIFF (1<<7) +///Will this skill use competency thresholds instead of preset values +#define MODIFIER_USE_THRESHOLDS (1<<8) + +#define MODIFIER_TARGET_VALUE "value" +#define MODIFIER_TARGET_LEVEL "level" +#define MODIFIER_TARGET_AFFINITY "affinity" + +///Ascending priority defines. +#define MODIFIER_SKILL_PRIORITY_LOW 100 +#define MODIFIER_SKILL_PRIORITY_DEF 50 +#define MODIFIER_SKILL_PRIORITY_MAX 1 //max priority, meant for job/antag modifiers so they don't null out other (de)buffs \ No newline at end of file diff --git a/code/__DEFINES/skills/helpers.dm b/code/__DEFINES/skills/helpers.dm new file mode 100644 index 0000000000..dde412fd7d --- /dev/null +++ b/code/__DEFINES/skills/helpers.dm @@ -0,0 +1,48 @@ + +//How experience levels are calculated. +#define XP_LEVEL(std, multi, lvl) (std*((multi**lvl)/(multi-1))-std/(multi-1)) //don't use 1 as multi, you'll get division by zero errors +#define DORF_XP_LEVEL(std, extra, lvl) (std*lvl+extra*(lvl*(lvl/2+0.5))) + +//More experience value getter macros +#define GET_STANDARD_LVL(lvl) XP_LEVEL(STD_XP_LVL_UP, STD_XP_LVL_MULTI, lvl) +#define GET_DORF_LVL(lvl) DORF_XP_LEVEL(DORF_XP_LVL_UP, DORF_XP_LVL_MULTI, lvl) + +#define IS_SKILL_VALUE_GREATER(path, existing, new_value) GLOB.skill_datums[path].is_value_greater(existing, new_value) + +#define SANITIZE_SKILL_VALUE(path, value) GLOB.skill_datums[path].sanitize_value(value) + +///Doesn't automatically round the value. +#define SANITIZE_SKILL_LEVEL(path, lvl) clamp(lvl, 0, GLOB.skill_datums[path].max_levels) + +/// Simple generic identifier macro. +#define GET_SKILL_MOD_ID(path, id) (id ? "[path]&[id]" : path) + +/** + * A simple universal comsig for body bound skill modifiers. + * Technically they are still bound to the mind, but other signal procs will take care of adding and removing the modifier + * from/to new/old minds. + */ +#define ADD_SKILL_MODIFIER_BODY(path, id, body, prototype) \ + prototype = GLOB.skill_modifiers[GET_SKILL_MOD_ID(path, id)] || new path(id, TRUE);\ + if(body.mind){\ + body.mind.add_skill_modifier(prototype.identifier)\ + } else {\ + prototype.RegisterSignal(body, COMSIG_MOB_ON_NEW_MIND, /datum/skill_modifier.proc/on_mob_new_mind, TRUE)\ + } + +/// Same as above but to remove the skill modifier. +#define REMOVE_SKILL_MODIFIER_BODY(path, id, body) \ + if(GLOB.skill_modifiers[GET_SKILL_MOD_ID(path, id)]){\ + if(body.mind){\ + body.mind.remove_skill_modifier(GET_SKILL_MOD_ID(path, id))\ + } else {\ + GLOB.skill_modifiers[GET_SKILL_MOD_ID(path, id)].UnregisterSignal(body, COMSIG_MOB_ON_NEW_MIND)\ + }\ + } + +///Macro used when adding generic singleton skill modifiers. +#define ADD_SINGLETON_SKILL_MODIFIER(mind, path, id) \ + if(!GLOB.skill_modifiers[GET_SKILL_MOD_ID(path, id)]){\ + new path(id, TRUE)\ + };\ + mind.add_skill_modifier(GET_SKILL_MOD_ID(path, id)) diff --git a/code/__DEFINES/skills/skills.dm b/code/__DEFINES/skills/skills.dm deleted file mode 100644 index b97b921550..0000000000 --- a/code/__DEFINES/skills/skills.dm +++ /dev/null @@ -1,28 +0,0 @@ -/// true/false -#define SKILL_PROGRESSION_BINARY 1 -/// numerical -#define SKILL_PROGRESSION_NUMERICAL 2 -/// Enum -#define SKILL_PROGRESSION_ENUM 3 - -/// Max value of skill for numerical skills -#define SKILL_NUMERICAL_MAX 100 -/// Min value of skill for numerical skills -#define SKILL_NUMERICAL_MIN 0 - -// Standard values for job starting skills - -#define STARTING_SKILL_SURGERY_MEDICAL 35 //out of SKILL_NUMERICAL_MAX - -// Standard values for job starting skill affinities - -#define STARTING_SKILL_AFFINITY_SURGERY_MEDICAL 1.2 - -// Standard values for skill gain (this is multiplied by affinity) - -#define SKILL_GAIN_SURGERY_PER_STEP 0.25 - -// Misc - -/// 40% speedup at 100 skill -#define SURGERY_SKILL_SPEEDUP_NUMERICAL_SCALE(number) clamp(number / 250, 1, 2) diff --git a/code/__DEFINES/storage.dm b/code/__DEFINES/storage/_storage.dm similarity index 79% rename from code/__DEFINES/storage.dm rename to code/__DEFINES/storage/_storage.dm index b4240455fe..3a05293d2d 100644 --- a/code/__DEFINES/storage.dm +++ b/code/__DEFINES/storage/_storage.dm @@ -11,7 +11,21 @@ #define STORAGE_LIMIT_MAX_W_CLASS (1<<3) #define STORAGE_FLAGS_LEGACY_DEFAULT (STORAGE_LIMIT_MAX_ITEMS | STORAGE_LIMIT_COMBINED_W_CLASS | STORAGE_LIMIT_MAX_W_CLASS) -#define STORAGE_FLAGS_VOLUME_DEFAULT (STORAGE_LIMIT_MAX_ITEMS | STORAGE_LIMIT_VOLUME | STORAGE_LIMIT_MAX_W_CLASS) +#define STORAGE_FLAGS_VOLUME_DEFAULT (STORAGE_LIMIT_VOLUME | STORAGE_LIMIT_MAX_W_CLASS) + +// UI defines +/// Size of volumetric box icon +#define VOLUMETRIC_STORAGE_BOX_ICON_SIZE 32 +/// Size of EACH left/right border icon for volumetric boxes +#define VOLUMETRIC_STORAGE_BOX_BORDER_SIZE 1 +/// Minimum pixels an item must have in volumetric scaled storage UI +#define MINIMUM_PIXELS_PER_ITEM 8 +/// Maximum number of objects that will be allowed to be displayed using the volumetric display system. Arbitrary number to prevent server lockups. +#define MAXIMUM_VOLUMETRIC_ITEMS 256 +/// How much padding to give between items +#define VOLUMETRIC_STORAGE_ITEM_PADDING 4 +/// How much padding to give to edges +#define VOLUMETRIC_STORAGE_EDGE_PADDING 1 //ITEM INVENTORY WEIGHT, FOR w_class /// Usually items smaller then a human hand, ex: Playing Cards, Lighter, Scalpel, Coins/Money @@ -26,22 +40,3 @@ #define WEIGHT_CLASS_HUGE 5 /// Essentially means it cannot be picked up or placed in an inventory, ex: Mech Parts, Safe - Can not fit in Boh #define WEIGHT_CLASS_GIGANTIC 6 - -/// Macro for automatically getting the volume of an item from its w_class. -#define AUTO_SCALE_VOLUME(w_class) (2 ** w_class) -/// Macro for automatically getting the volume of a storage item from its max_w_class and max_combined_w_class. -#define AUTO_SCALE_STORAGE_VOLUME(w_class, max_combined_w_class) (AUTO_SCALE_VOLUME(w_class) * (max_combined_w_class / w_class)) - -// UI defines -/// Size of volumetric box icon -#define VOLUMETRIC_STORAGE_BOX_ICON_SIZE 32 -/// Size of EACH left/right border icon for volumetric boxes -#define VOLUMETRIC_STORAGE_BOX_BORDER_SIZE 1 -/// Minimum pixels an item must have in volumetric scaled storage UI -#define MINIMUM_PIXELS_PER_ITEM 6 -/// Maximum number of objects that will be allowed to be displayed using the volumetric display system. Arbitrary number to prevent server lockups. -#define MAXIMUM_VOLUMETRIC_ITEMS 256 -/// How much padding to give between items -#define VOLUMETRIC_STORAGE_ITEM_PADDING 1 -/// How much padding to give to edges -#define VOLUMETRIC_STORAGE_EDGE_PADDING 1 diff --git a/code/__DEFINES/storage/volumetrics.dm b/code/__DEFINES/storage/volumetrics.dm new file mode 100644 index 0000000000..62eaa226c4 --- /dev/null +++ b/code/__DEFINES/storage/volumetrics.dm @@ -0,0 +1,39 @@ +// PLEASE KEEP ALL VOLUME DEFINES IN THIS FILE, it's going to be hell to keep track of them later. + +#define DEFAULT_VOLUME_TINY 2 +#define DEFAULT_VOLUME_SMALL 3 +#define DEFAULT_VOLUME_NORMAL 4 +#define DEFAULT_VOLUME_BULKY 8 +#define DEFAULT_VOLUME_HUGE 16 +#define DEFAULT_VOLUME_GIGANTIC 32 + +GLOBAL_LIST_INIT(default_weight_class_to_volume, list( + "[WEIGHT_CLASS_TINY]" = DEFAULT_VOLUME_TINY, + "[WEIGHT_CLASS_SMALL]" = DEFAULT_VOLUME_SMALL, + "[WEIGHT_CLASS_NORMAL]" = DEFAULT_VOLUME_NORMAL, + "[WEIGHT_CLASS_BULKY]" = DEFAULT_VOLUME_BULKY, + "[WEIGHT_CLASS_HUGE]" = DEFAULT_VOLUME_HUGE, + "[WEIGHT_CLASS_GIGANTIC]" = DEFAULT_VOLUME_GIGANTIC + )) + +/// Macro for automatically getting the volume of an item from its w_class. +#define AUTO_SCALE_VOLUME(w_class) (GLOB.default_weight_class_to_volume["[w_class]"]) +/// Macro for automatically getting the volume of a storage item from its max_w_class and max_combined_w_class. +#define AUTO_SCALE_STORAGE_VOLUME(w_class, max_combined_w_class) (AUTO_SCALE_VOLUME(w_class) * (max_combined_w_class / w_class)) + +// Let's keep all of this in one place. given what we put above anyways.. + +// volume amount for items +#define ITEM_VOLUME_DISK DEFAULT_VOLUME_TINY + +// #define SAMPLE_VOLUME_AMOUNT 2 + +// max_weight_class for storages +#define MAX_WEIGHT_CLASS_BACKPACK WEIGHT_CLASS_NORMAL +#define MAX_WEIGHT_CLASS_BAG_OF_HOLDING WEIGHT_CLASS_BULKY + +// max_volume for storages +#define STORAGE_VOLUME_BACKPACK (DEFAULT_VOLUME_NORMAL * 7) +#define STORAGE_VOLUME_DUFFLEBAG (DEFAULT_VOLUME_NORMAL * 10) +#define STORAGE_VOLUME_BAG_OF_HOLDING (DEFAULT_VOLUME_NORMAL * 20) + diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 3abef3a61c..8c423ad09c 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -64,7 +64,8 @@ #define INIT_ORDER_TICKER 55 #define INIT_ORDER_INSTRUMENTS 53 #define INIT_ORDER_MAPPING 50 -#define INIT_ORDER_NETWORKS 45 +#define INIT_ORDER_ECONOMY 45 +#define INIT_ORDER_NETWORKS 40 #define INIT_ORDER_HOLODECK 35 #define INIT_ORDER_ATOMS 30 #define INIT_ORDER_LANGUAGE 25 @@ -116,6 +117,7 @@ #define FIRE_PRIORITY_NPC 80 #define FIRE_PRIORITY_MOBS 100 #define FIRE_PRIORITY_TGUI 110 +#define FIRE_PRIORITY_PROJECTILES 200 #define FIRE_PRIORITY_TICKER 200 #define FIRE_PRIORITY_ATMOS_ADJACENCY 300 #define FIRE_PRIORITY_CHAT 400 diff --git a/code/__DEFINES/tgs.config.dm b/code/__DEFINES/tgs.config.dm index 9f4f63a1fc..a2fcc7855a 100644 --- a/code/__DEFINES/tgs.config.dm +++ b/code/__DEFINES/tgs.config.dm @@ -4,8 +4,9 @@ #define TGS_READ_GLOBAL(Name) GLOB.##Name #define TGS_WRITE_GLOBAL(Name, Value) GLOB.##Name = ##Value #define TGS_WORLD_ANNOUNCE(message) to_chat(world, "[html_encode(##message)]") -#define TGS_INFO_LOG(message) log_world("TGS: Info: [##message]") -#define TGS_ERROR_LOG(message) log_world("TGS: Error: [##message]") +#define TGS_INFO_LOG(message) log_world("TGS Info: [##message]") +#define TGS_WARNING_LOG(message) log_world("TGS Warn: [##message]") +#define TGS_ERROR_LOG(message) log_world("TGS Error: [##message]") #define TGS_NOTIFY_ADMINS(event) message_admins(##event) #define TGS_CLIENT_COUNT GLOB.clients.len #define TGS_PROTECT_DATUM(Path) GENERAL_PROTECT_DATUM(##Path) diff --git a/code/__DEFINES/tgs.dm b/code/__DEFINES/tgs.dm index dcccfc9295..e164a4ec96 100644 --- a/code/__DEFINES/tgs.dm +++ b/code/__DEFINES/tgs.dm @@ -1,5 +1,7 @@ //tgstation-server DMAPI +#define TGS_DMAPI_VERSION "5.1.1" + //All functions and datums outside this document are subject to change with any version and should not be relied on //CONFIGURATION @@ -17,7 +19,6 @@ //Required interfaces (fill in with your codebase equivalent): //create a global variable named `Name` and set it to `Value` -//These globals must not be modifiable from anywhere outside of the server tools #define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) //Read the value in the global variable `Name` @@ -26,10 +27,10 @@ //Set the value in the global variable `Name` to `Value` #define TGS_WRITE_GLOBAL(Name, Value) -//Disallow ANYONE from reflecting a given `path`, security measure to prevent in-game priveledge escalation +//Disallow ANYONE from reflecting a given `path`, security measure to prevent in-game use of DD -> TGS capabilities #define TGS_PROTECT_DATUM(Path) -//display an announcement `message` from the server to all players +//Display an announcement `message` from the server to all players #define TGS_WORLD_ANNOUNCE(message) //Notify current in-game administrators of a string `event` @@ -38,6 +39,9 @@ //Write an info `message` to a server log #define TGS_INFO_LOG(message) +//Write an warning `message` to a server log +#define TGS_WARNING_LOG(message) + //Write an error `message` to a server log #define TGS_ERROR_LOG(message) @@ -48,10 +52,12 @@ //EVENT CODES -#define TGS_EVENT_PORT_SWAP -2 //before a port change is about to happen, extra parameter is new port -#define TGS_EVENT_REBOOT_MODE_CHANGE -1 //before a reboot mode change, extras parameters are the current and new reboot mode enums +#define TGS_EVENT_REBOOT_MODE_CHANGE -1 //Before a reboot mode change, extras parameters are the current and new reboot mode enums +#define TGS_EVENT_PORT_SWAP -2 //Before a port change is about to happen, extra parameters is new port +#define TGS_EVENT_INSTANCE_RENAMED -3 //Before the instance is renamed, extra parameter is the new name +#define TGS_EVENT_WATCHDOG_REATTACH -4 //After the watchdog reattaches to DD, extra parameter is the new /datum/tgs_version of the server -//See the descriptions for these codes here: https://github.com/tgstation/tgstation-server/blob/master/src/Tgstation.Server.Host/Components/EventType.cs +//See the descriptions for the parameters of these codes here: https://github.com/tgstation/tgstation-server/blob/master/src/Tgstation.Server.Host/Components/EventType.cs #define TGS_EVENT_REPO_RESET_ORIGIN 0 #define TGS_EVENT_REPO_CHECKOUT 1 #define TGS_EVENT_REPO_FETCH 2 @@ -63,9 +69,12 @@ #define TGS_EVENT_COMPILE_START 8 #define TGS_EVENT_COMPILE_CANCELLED 9 #define TGS_EVENT_COMPILE_FAILURE 10 -#define TGS_EVENT_COMPILE_COMPLETE 11 +#define TGS_EVENT_COMPILE_COMPLETE 11 // Note, this event fires before the new .dmb is loaded into the watchdog. Consider using the TGS_EVENT_DEPLOYMENT_COMPLETE instead #define TGS_EVENT_INSTANCE_AUTO_UPDATE_START 12 #define TGS_EVENT_REPO_MERGE_CONFLICT 13 +#define TGS_EVENT_DEPLOYMENT_COMPLETE 14 +#define TGS_EVENT_WATCHDOG_SHUTDOWN 15 +#define TGS_EVENT_WATCHDOG_DETACH 16 //OTHER ENUMS @@ -80,6 +89,7 @@ //REQUIRED HOOKS //Call this somewhere in /world/New() that is always run +//IMPORTANT: This function may sleep! //event_handler: optional user defined event handler. The default behaviour is to broadcast the event in english to all connected admin channels //minimum_required_security_level: The minimum required security level to run the game in which the DMAPI is integrated /world/proc/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE) @@ -109,12 +119,12 @@ //represents a version of tgstation-server /datum/tgs_version - var/suite //The suite version, can be >=3 + var/suite //The suite/major version, can be >=3 //this group of variables can be null to represent a wild card - var/major //The major version var/minor //The minor version var/patch //The patch version + var/deprecated_patch //The legacy version var/raw_parameter //The unparsed parameter var/deprefixed_parameter //The version only bit of raw_parameter @@ -123,6 +133,10 @@ /datum/tgs_version/proc/Wildcard() return +//if the tgs_version equals some other_version +/datum/tgs_version/proc/Equals(datum/tgs_version/other_version) + return + //represents a merge of a GitHub pull request /datum/tgs_revision_information/test_merge var/number //pull request number @@ -179,14 +193,45 @@ return //Returns TRUE if the world was launched under the server tools and the API matches, FALSE otherwise -//No function below this succeeds if it returns FALSE +//No function below this succeeds if it returns FALSE or if TgsNew() has yet to be called /world/proc/TgsAvailable() return +//Forces a hard reboot of BYOND by ending the process +//unlike del(world) clients will try to reconnect +//If the service has not requested a shutdown, the next server will take over +/world/proc/TgsEndProcess() + return + +//Send a message to non-admin connected chats +//message: The message to send +//admin_only: If TRUE, message will instead be sent to only admin connected chats +/world/proc/TgsTargetedChatBroadcast(message, admin_only) + return + +//Send a private message to a specific user +//message: The message to send +//user: The /datum/tgs_chat_user to send to +/world/proc/TgsChatPrivateMessage(message, datum/tgs_chat_user/user) + return + +//The following functions will sleep if a call to TgsNew() is sleeping + +//Sends a message to connected game chats +//message: The message to send +//channels: optional channels to limit the broadcast to +/world/proc/TgsChatBroadcast(message, list/channels) + return + //Gets the current /datum/tgs_version of the server tools running the server /world/proc/TgsVersion() return +//Gets the current /datum/tgs_version of the DMAPI being used +/world/proc/TgsApiVersion() + return + +//Gets the name of the TGS instance running the game /world/proc/TgsInstanceName() return @@ -202,34 +247,10 @@ /world/proc/TgsTestMerges() return -//Forces a hard reboot of BYOND by ending the process -//unlike del(world) clients will try to reconnect -//If the service has not requested a shutdown, the next server will take over -/world/proc/TgsEndProcess() - return - //Gets a list of connected tgs_chat_channel /world/proc/TgsChatChannelInfo() return -//Sends a message to connected game chats -//message: The message to send -//channels: optional channels to limit the broadcast to -/world/proc/TgsChatBroadcast(message, list/channels) - return - -//Send a message to non-admin connected chats -//message: The message to send -//admin_only: If TRUE, message will instead be sent to only admin connected chats -/world/proc/TgsTargetedChatBroadcast(message, admin_only) - return - -//Send a private message to a specific user -//message: The message to send -//user: The /datum/tgs_chat_user to send to -/world/proc/TgsChatPrivateMessage(message, datum/tgs_chat_user/user) - return - /* The MIT License @@ -255,4 +276,4 @@ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ \ No newline at end of file +*/ diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index d5687fd4ad..7b14c6215c 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -88,6 +88,7 @@ #define TRAIT_SLEEPIMMUNE "sleep_immunity" #define TRAIT_PUSHIMMUNE "push_immunity" #define TRAIT_SHOCKIMMUNE "shock_immunity" +#define TRAIT_TESLA_SHOCKIMMUNE "tesla_shock_immunity" #define TRAIT_STABLEHEART "stable_heart" #define TRAIT_STABLELIVER "stable_liver" #define TRAIT_RESISTHEAT "resist_heat" @@ -134,6 +135,7 @@ #define TRAIT_LAW_ENFORCEMENT_METABOLISM "law-enforcement-metabolism" #define TRAIT_QUICK_CARRY "quick-carry" #define TRAIT_QUICKER_CARRY "quicker-carry" +#define TRAIT_QUICK_BUILD "quick-build" #define TRAIT_STRONG_GRABBER "strong_grabber" #define TRAIT_CALCIUM_HEALER "calcium_healer" #define TRAIT_MAGIC_CHOKE "magic_choke" @@ -146,6 +148,8 @@ #define TRAIT_NORUNNING "norunning" // You walk! #define TRAIT_NOMARROW "nomarrow" // You don't make blood, with chemicals or nanites. #define TRAIT_NOPULSE "nopulse" // Your heart doesn't beat. +#define TRAIT_NOGUT "nogutting" //Your chest cant be gutted of organs +#define TRAIT_NODECAP "nodecapping" //Your head cant be cut off in combat #define TRAIT_EXEMPT_HEALTH_EVENTS "exempt-health-events" #define TRAIT_NO_MIDROUND_ANTAG "no-midround-antag" //can't be turned into an antag by random events #define TRAIT_PUGILIST "pugilist" //This guy punches people for a living diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm index a364e0b93c..889e1bb1c0 100644 --- a/code/__DEFINES/vv.dm +++ b/code/__DEFINES/vv.dm @@ -122,3 +122,6 @@ // misc #define VV_HK_SPACEVINE_PURGE "spacevine_purge" + +// paintings +#define VV_HK_REMOVE_PAINTING "remove_painting" diff --git a/code/__HELPERS/_cit_helpers.dm b/code/__HELPERS/_cit_helpers.dm index 5f78aeb740..5e57dd5328 100644 --- a/code/__HELPERS/_cit_helpers.dm +++ b/code/__HELPERS/_cit_helpers.dm @@ -1,9 +1,6 @@ //THIS FILE CONTAINS CONSTANTS, PROCS, AND OTHER THINGS// ///////////////////////////////////////////////////////// -/mob/proc/setClickCooldown(var/timeout) - next_move = max(world.time + timeout, next_move) - /proc/get_matrix_largest() var/matrix/mtrx=new() return mtrx.Scale(2) @@ -105,16 +102,6 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE) if(!src.holder) return message_admins("[key_name_admin(usr)] manually reloaded mentors") -//LOOC toggles -/client/verb/listen_looc() - set name = "Show/Hide LOOC" - set category = "Preferences" - set desc = "Toggles seeing LocalOutOfCharacter chat" - prefs.chat_toggles ^= CHAT_LOOC - prefs.save_preferences() - to_chat(src, "You will [(prefs.chat_toggles & CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel.") - SSblackbox.record_feedback("tally", "admin_verb", 1, "TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - /mob/living/carbon/proc/has_penis() var/obj/item/organ/genital/G = getorganslot(ORGAN_SLOT_PENIS) if(G && istype(G, /obj/item/organ/genital/penis)) diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index ad977ec493..ba29205452 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -37,6 +37,7 @@ * TYPECONT: The typepath of the contents of the list * COMPARE: The object to compare against, usualy the same as INPUT * COMPARISON: The variable on the objects to compare + * COMPTYPE: How the current bin item to compare against COMPARE is fetched. By key or value. */ #define BINARY_INSERT(INPUT, LIST, TYPECONT, COMPARE, COMPARISON, COMPTYPE) \ do {\ @@ -629,6 +630,8 @@ L["[key]"] = "[value]" return list2params(L) +#define NUMLIST2TEXTLIST(list) splittext(list2params(list), "&") + //Picks from the list, with some safeties, and returns the "default" arg if it fails #define DEFAULTPICK(L, default) ((islist(L) && length(L)) ? pick(L) : default) @@ -668,3 +671,13 @@ for(var/key in input) ret += key return ret + +/proc/is_type_in_ref_list(path, list/L) + if(!ispath(path))//not a path + return + for(var/i in L) + var/datum/D = i + if(!istype(D))//not an usable reference + continue + if(istype(D, path)) + return TRUE diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 8ef924eea4..5e0ac99bae 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -4,7 +4,9 @@ #define SEND_SOUND(target, sound) DIRECT_OUTPUT(target, sound) #define SEND_TEXT(target, text) DIRECT_OUTPUT(target, text) #define WRITE_FILE(file, text) DIRECT_OUTPUT(file, text) -#define WRITE_LOG(log, text) rustg_log_write(log, text) +//This is an external call, "true" and "false" are how rust parses out booleans +#define WRITE_LOG(log, text) rustg_log_write(log, text, "true") +#define WRITE_LOG_NO_FORMAT(log, text) rustg_log_write(log, text, "false") //print a warning message to world.log #define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [UNLINT(src)] usr: [usr].") @@ -152,6 +154,9 @@ /proc/log_subsystem(subsystem, text) WRITE_LOG(GLOB.subsystem_log, "[subsystem]: [text]") +/proc/log_click(object, location, control, params, client/C, event = "clicked") + WRITE_LOG(GLOB.click_log, "CLICK: [C.ckey] - [event] : [object] | [location] | [control] | [params]") + /* Log to both DD and the logfile. */ /proc/log_world(text) #ifdef USE_CUSTOM_ERROR_HANDLER @@ -181,7 +186,7 @@ /proc/start_log(log) WRITE_LOG(log, "Starting up round ID [GLOB.round_id].\n-------------------------") -/* ui logging */ +/* ui logging */ /proc/log_tgui(text) WRITE_LOG(GLOB.tgui_log, text) diff --git a/code/__HELPERS/angles.dm b/code/__HELPERS/angles.dm new file mode 100644 index 0000000000..a3fc2404bd --- /dev/null +++ b/code/__HELPERS/angles.dm @@ -0,0 +1,39 @@ +/proc/get_projectile_angle(atom/source, atom/target) + var/sx = source.x * world.icon_size + var/sy = source.y * world.icon_size + var/tx = target.x * world.icon_size + var/ty = target.y * world.icon_size + var/atom/movable/AM + if(ismovable(source)) + AM = source + sx += AM.step_x + sy += AM.step_y + if(ismovable(target)) + AM = target + tx += AM.step_x + ty += AM.step_y + return SIMPLIFY_DEGREES(arctan(ty - sy, tx - sx)) + +/proc/Get_Angle(atom/movable/start,atom/movable/end)//For beams. + if(!start || !end) + return 0 + var/dy + var/dx + dy=(32*end.y+end.pixel_y)-(32*start.y+start.pixel_y) + dx=(32*end.x+end.pixel_x)-(32*start.x+start.pixel_x) + if(!dy) + return (dx>=0)?90:270 + .=arctan(dx/dy) + if(dy<0) + .+=180 + else if(dx<0) + .+=360 + +/proc/Get_Pixel_Angle(var/y, var/x)//for getting the angle when animating something's pixel_x and pixel_y + if(!y) + return (x>=0)?90:270 + .=arctan(x/y) + if(y<0) + .+=180 + else if(x<0) + .+=360 diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 170d93c31f..75ac6a8b26 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -249,6 +249,15 @@ SEND_SIGNAL(A, COMSIG_ATOM_HEARER_IN_VIEW, processing, .) processing += A.contents +//viewers() but with a signal, for blacklisting. +/proc/fov_viewers(depth = world.view, atom/center) + if(!center) + return + . = viewers(depth, center) + for(var/k in .) + var/mob/M = k + SEND_SIGNAL(M, COMSIG_MOB_FOV_VIEWER, center, depth, .) + /proc/get_mobs_in_radio_ranges(list/obj/item/radio/radios) . = list() // Returns a list of mobs who can hear any of the radios given in @radios @@ -506,6 +515,19 @@ return winset(C, "mainwindow", "flash=5") +//Recursively checks if an item is inside a given type, even through layers of storage. Returns the atom if it finds it. +/proc/recursive_loc_check(atom/movable/target, type) + var/atom/A = target + if(istype(A, type)) + return A + + while(!istype(A.loc, type)) + if(!A.loc) + return + A = A.loc + + return A.loc + /proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank) if(!SSticker.IsRoundInProgress() || QDELETED(character)) return diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index bcfaa1bed2..0b5c60a95a 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -75,6 +75,8 @@ var/datum/emote/E = new path() E.emote_list[E.key] = E + init_keybindings() + //Uplink Items for(var/path in subtypesof(/datum/uplink_item)) var/datum/uplink_item/I = path diff --git a/code/__HELPERS/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm index dadd4322fb..cbe1817233 100644 --- a/code/__HELPERS/sanitize_values.dm +++ b/code/__HELPERS/sanitize_values.dm @@ -18,6 +18,12 @@ return text return default +/proc/sanitize_islist(value, default) + if(islist(value) && length(value)) + return value + if(default) + return default + /proc/sanitize_inlist(value, list/List, default) if(value in List) return value diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 09047d32bf..2c8497d5ed 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -629,3 +629,45 @@ return null r += ascii2text(c) return r + +/proc/slot_to_string(slot) + switch(slot) + if(SLOT_BACK) + return "Backpack" + if(SLOT_WEAR_MASK) + return "Mask" + if(SLOT_HANDS) + return "Hands" + if(SLOT_BELT) + return "Belt" + if(SLOT_EARS) + return "Ears" + if(SLOT_GLASSES) + return "Glasses" + if(SLOT_GLOVES) + return "Gloves" + if(SLOT_NECK) + return "Neck" + if(SLOT_HEAD) + return "Head" + if(SLOT_SHOES) + return "Shoes" + if(SLOT_WEAR_SUIT) + return "Suit" + if(SLOT_W_UNIFORM) + return "Uniform" + if(SLOT_IN_BACKPACK) + return "In backpack" + +/proc/tg_ui_icon_to_cit_ui(ui_style) + switch(ui_style) + if('icons/mob/screen_plasmafire.dmi') + return 'modular_citadel/icons/ui/screen_plasmafire.dmi' + if('icons/mob/screen_slimecore.dmi') + return 'modular_citadel/icons/ui/screen_slimecore.dmi' + if('icons/mob/screen_operative.dmi') + return 'modular_citadel/icons/ui/screen_operative.dmi' + if('icons/mob/screen_clockwork.dmi') + return 'modular_citadel/icons/ui/screen_clockwork.dmi' + else + return 'modular_citadel/icons/ui/screen_midnight.dmi' diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 13ac820778..919c4c879f 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1,5 +1,3 @@ - - /* * A large number of misc global procs. */ @@ -17,30 +15,6 @@ var/textb = copytext(HTMLstring, 6, 8) return rgb(255 - hex2num(textr), 255 - hex2num(textg), 255 - hex2num(textb)) -/proc/Get_Angle(atom/movable/start,atom/movable/end)//For beams. - if(!start || !end) - return 0 - var/dy - var/dx - dy=(32*end.y+end.pixel_y)-(32*start.y+start.pixel_y) - dx=(32*end.x+end.pixel_x)-(32*start.x+start.pixel_x) - if(!dy) - return (dx>=0)?90:270 - .=arctan(dx/dy) - if(dy<0) - .+=180 - else if(dx<0) - .+=360 - -/proc/Get_Pixel_Angle(var/y, var/x)//for getting the angle when animating something's pixel_x and pixel_y - if(!y) - return (x>=0)?90:270 - .=arctan(x/y) - if(y<0) - .+=180 - else if(x<0) - .+=360 - //Returns location. Returns null if no location was found. /proc/get_teleport_loc(turf/location,mob/target,distance = 1, density = FALSE, errorx = 0, errory = 0, eoffsetx = 0, eoffsety = 0) /* @@ -391,6 +365,16 @@ Turf and target are separate in case you want to teleport some distance from a t break return loc +//Returns a list of all locations the target is within. +/proc/get_nested_locs(atom/movable/M, include_turf = FALSE) + . = list() + var/atom/A = M.loc + while(A && !isturf(A)) + . += A + A = A.loc + if(A && include_turf) //At this point, only the turf is left. + . += A + // returns the turf located at the map edge in the specified direction relative to A // used for mass driver /proc/get_edge_target_turf(atom/A, direction) @@ -1048,6 +1032,27 @@ B --><-- A /proc/get_random_station_turf() return safepick(get_area_turfs(pick(GLOB.the_station_areas))) +/proc/get_safe_random_station_turf() //excludes dense turfs (like walls) and areas that have valid_territory set to FALSE + for (var/i in 1 to 5) + var/list/L = get_area_turfs(pick(GLOB.the_station_areas)) + var/turf/target + while (L.len && !target) + var/I = rand(1, L.len) + var/turf/T = L[I] + var/area/X = get_area(T) + if(!T.density && X.valid_territory) + var/clear = TRUE + for(var/obj/O in T) + if(O.density) + clear = FALSE + break + if(clear) + target = T + if (!target) + L.Cut(I,I+1) + if (target) + return target + /proc/get_closest_atom(type, list, source) var/closest_atom var/closest_distance @@ -1571,8 +1576,13 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) //empty string - use TgsTargetBroadcast with admin_only = FALSE //other string - use TgsChatBroadcast with the tag that matches config_setting, only works with TGS4, if using TGS3 the above method is used /proc/send2chat(message, config_setting) - if(config_setting == null || !world.TgsAvailable()) + if(config_setting == null) return + + UNTIL(GLOB.tgs_initialized) + if(!world.TgsAvailable()) + return + var/datum/tgs_version/version = world.TgsVersion() if(config_setting == "" || version.suite == 3) world.TgsTargetedChatBroadcast(message, FALSE) diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 5659d730fb..2b6c387810 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -134,9 +134,11 @@ GLOBAL_LIST_INIT(bitfields, list( "NO_RUINS_1" = NO_RUINS_1, "PREVENT_CLICK_UNDER_1" = PREVENT_CLICK_UNDER_1, "HOLOGRAM_1" = HOLOGRAM_1, - "TESLA_IGNORE_1" = TESLA_IGNORE_1, + "SHOCKED_1" = SHOCKED_1, "INITIALIZED_1" = INITIALIZED_1, "ADMIN_SPAWNED_1" = ADMIN_SPAWNED_1, + "BLOCK_FACE_ATOM_1" = BLOCK_FACE_ATOM_1, + "PREVENT_CONTENTS_EXPLOSION_1" = PREVENT_CONTENTS_EXPLOSION_1 ), "clothing_flags" = list( "LAVAPROTECT" = LAVAPROTECT, @@ -150,12 +152,12 @@ GLOBAL_LIST_INIT(bitfields, list( "IGNORE_HAT_TOSS" = IGNORE_HAT_TOSS, "SCAN_REAGENTS" = SCAN_REAGENTS ), - "tesla_flags" = list( - "TESLA_MOB_DAMAGE" = TESLA_MOB_DAMAGE, - "TESLA_OBJ_DAMAGE" = TESLA_OBJ_DAMAGE, - "TESLA_MOB_STUN" = TESLA_MOB_STUN, - "TESLA_ALLOW_DUPLICATES" = TESLA_ALLOW_DUPLICATES, - "TESLA_MACHINE_EXPLOSIVE" = TESLA_MACHINE_EXPLOSIVE, + "zap_flags" = list( + "ZAP_MOB_DAMAGE" = ZAP_MOB_DAMAGE, + "ZAP_OBJ_DAMAGE" = ZAP_OBJ_DAMAGE, + "ZAP_MOB_STUN" = ZAP_MOB_STUN, + "ZAP_ALLOW_DUPLICATES" = ZAP_ALLOW_DUPLICATES, + "ZAP_MACHINE_EXPLOSIVE" = ZAP_MACHINE_EXPLOSIVE, ), "smooth" = list( "SMOOTH_TRUE" = SMOOTH_TRUE, diff --git a/code/_globalvars/lists/client.dm b/code/_globalvars/lists/client.dm new file mode 100644 index 0000000000..5181d870c4 --- /dev/null +++ b/code/_globalvars/lists/client.dm @@ -0,0 +1,21 @@ +GLOBAL_LIST_EMPTY(classic_keybinding_list_by_key) +GLOBAL_LIST_EMPTY(hotkey_keybinding_list_by_key) +GLOBAL_LIST_EMPTY(keybindings_by_name) + +// This is a mapping from JS keys to Byond - ref: https://keycode.info/ +GLOBAL_LIST_INIT(_kbMap, list( + "UP" = "North", + "RIGHT" = "East", + "DOWN" = "South", + "LEFT" = "West", + "INSERT" = "Insert", + "HOME" = "Northwest", + "PAGEUP" = "Northeast", + "DEL" = "Delete", + "END" = "Southwest", + "PAGEDOWN" = "Southeast", + "SPACEBAR" = "Space", + "ALT" = "Alt", + "SHIFT" = "Shift", + "CONTROL" = "Ctrl" + )) diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index aacb1737a2..df83f1b4e3 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -221,3 +221,5 @@ GLOBAL_LIST_INIT(numbers_as_words, world.file2list("strings/numbers_as_words.txt GLOBAL_LIST_INIT(station_numerals, greek_letters + phonetic_alphabet + numbers_as_words + generate_number_strings()) GLOBAL_LIST_INIT(admiral_messages, list("Do you know how expensive these stations are?","Stop wasting my time.","I was sleeping, thanks a lot.","Stand and fight you cowards!","You knew the risks coming in.","Stop being paranoid.","Whatever's broken just build a new one.","No.", "null","Error: No comment given.", "It's a good day to die!")) + +GLOBAL_LIST_INIT(redacted_strings, list("\[REDACTED\]", "\[CLASSIFIED\]", "\[ARCHIVED\]", "\[EXPLETIVE DELETED\]", "\[EXPUNGED\]", "\[INFORMATION ABOVE YOUR SECURITY CLEARANCE\]", "\[MOVE ALONG CITIZEN\]", "\[NOTHING TO SEE HERE\]", "\[ACCESS DENIED\]")) diff --git a/code/_globalvars/lists/keybindings.dm b/code/_globalvars/lists/keybindings.dm new file mode 100644 index 0000000000..7e5b016a95 --- /dev/null +++ b/code/_globalvars/lists/keybindings.dm @@ -0,0 +1,31 @@ +/// Creates and sorts all the keybinding datums +/proc/init_keybindings() + for(var/KB in subtypesof(/datum/keybinding)) + var/datum/keybinding/keybinding = KB + if(!initial(keybinding.hotkey_keys)) + continue + add_keybinding(new keybinding) + // init_emote_keybinds() - Disabled - I don't particularly want this. + +/// Adds an instanced keybinding to the global tracker +/proc/add_keybinding(datum/keybinding/instance) + GLOB.keybindings_by_name[instance.name] = instance + + // Classic + if(LAZYLEN(instance.classic_keys)) + for(var/bound_key in instance.classic_keys) + LAZYADD(GLOB.classic_keybinding_list_by_key[bound_key], list(instance.name)) + + // Hotkey + if(LAZYLEN(instance.hotkey_keys)) + for(var/bound_key in instance.hotkey_keys) + LAZYADD(GLOB.hotkey_keybinding_list_by_key[bound_key], list(instance.name)) + +/proc/init_emote_keybinds() + for(var/i in subtypesof(/datum/emote)) + var/datum/emote/faketype = i + if(!initial(faketype.key)) + continue + var/datum/keybinding/emote/emote_kb = new + emote_kb.link_to_emote(faketype) + add_keybinding(emote_kb) diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm index ba75fbfc9c..65fd772dfe 100644 --- a/code/_globalvars/logging.dm +++ b/code/_globalvars/logging.dm @@ -36,6 +36,8 @@ GLOBAL_VAR(reagent_log) GLOBAL_PROTECT(reagent_log) GLOBAL_VAR(world_crafting_log) GLOBAL_PROTECT(world_crafting_log) +GLOBAL_VAR(click_log) +GLOBAL_PROTECT(click_log) GLOBAL_LIST_EMPTY(bombers) GLOBAL_PROTECT(bombers) diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index dd8b9f0d94..1b100bebaf 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -29,6 +29,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_SLEEPIMMUNE" = TRAIT_SLEEPIMMUNE, "TRAIT_PUSHIMMUNE" = TRAIT_PUSHIMMUNE, "TRAIT_SHOCKIMMUNE" = TRAIT_SHOCKIMMUNE, + "TRAIT_TESLA_SHOCKIMMUNE" = TRAIT_TESLA_SHOCKIMMUNE, "TRAIT_STABLEHEART" = TRAIT_STABLEHEART, "TRAIT_STABLELIVER" = TRAIT_STABLELIVER, "TRAIT_RESISTHEAT" = TRAIT_RESISTHEAT, diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index ed3e255722..ca6172f714 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -80,7 +80,7 @@ if(SEND_SIGNAL(src, COMSIG_MOB_CLICKON, A, params) & COMSIG_MOB_CANCEL_CLICKON) return - + var/list/modifiers = params2list(params) if(modifiers["shift"] && modifiers["middle"]) ShiftMiddleClickOn(A) @@ -327,10 +327,9 @@ return /atom/proc/ShiftClick(mob/user) - var/flags = SEND_SIGNAL(src, COMSIG_CLICK_SHIFT, user) + var/flags = SEND_SIGNAL(src, COMSIG_CLICK_SHIFT, user) | SEND_SIGNAL(user, COMSIG_MOB_CLICKED_SHIFT_ON, src) if(!(flags & COMPONENT_DENY_EXAMINATE) && user.client && (user.client.eye == user || user.client.eye == user.loc || flags & COMPONENT_ALLOW_EXAMINATE)) user.examinate(src) - return /* Ctrl click @@ -427,32 +426,36 @@ LE.fire() // Simple helper to face what you clicked on, in case it should be needed in more than one place -/mob/proc/face_atom(atom/A) - if( buckled || stat != CONSCIOUS || !A || !x || !y || !A.x || !A.y ) +/mob/proc/face_atom(atom/A, ismousemovement = FALSE) + if( buckled || stat != CONSCIOUS || !loc || !A || !A.x || !A.y ) return - var/dx = A.x - x - var/dy = A.y - y + var/atom/L = loc + if(L.flags_1 & BLOCK_FACE_ATOM_1) + return + var/turf/T = get_turf(src) + var/dx = A.x - T.x + var/dy = A.y - T.y if(!dx && !dy) // Wall items are graphically shifted but on the floor if(A.pixel_y > 16) - setDir(NORTH) + setDir(NORTH, ismousemovement) else if(A.pixel_y < -16) - setDir(SOUTH) + setDir(SOUTH, ismousemovement) else if(A.pixel_x > 16) - setDir(EAST) + setDir(EAST, ismousemovement) else if(A.pixel_x < -16) - setDir(WEST) + setDir(WEST, ismousemovement) return if(abs(dx) < abs(dy)) if(dy > 0) - setDir(NORTH) + setDir(NORTH, ismousemovement) else - setDir(SOUTH) + setDir(SOUTH, ismousemovement) else if(dx > 0) - setDir(EAST) + setDir(EAST, ismousemovement) else - setDir(WEST) + setDir(WEST, ismousemovement) //debug /obj/screen/proc/scale_to(x1,y1) diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 328e008f10..f281853b0f 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -241,13 +241,13 @@ using.hud = src hotkeybuttons += using - //CIT CHANGES - rest and combat mode buttons - using = new /obj/screen/restbutton() - using.icon = tg_ui_icon_to_cit_ui(ui_style) + using = new /obj/screen/rest() + using.icon = ui_style using.screen_loc = ui_pull_resist using.hud = src static_inventory += using + //CIT CHANGES - combat mode buttons using = new /obj/screen/combattoggle() using.icon = tg_ui_icon_to_cit_ui(ui_style) using.screen_loc = ui_combat_toggle diff --git a/code/_onclick/hud/plane_master.dm b/code/_onclick/hud/plane_master.dm index a0dade37bd..7a8b0a1121 100644 --- a/code/_onclick/hud/plane_master.dm +++ b/code/_onclick/hud/plane_master.dm @@ -24,6 +24,10 @@ blend_mode = BLEND_MULTIPLY alpha = 255 +/obj/screen/plane_master/openspace/Initialize() + . = ..() + filters += filter(type="alpha", render_source=FIELD_OF_VISION_RENDER_TARGET, flags=MASK_INVERSE) + /obj/screen/plane_master/openspace/backdrop(mob/mymob) filters = list() filters += filter(type = "drop_shadow", color = "#04080FAA", size = -10) @@ -46,6 +50,32 @@ appearance_flags = PLANE_MASTER blend_mode = BLEND_OVERLAY +/obj/screen/plane_master/wall + name = "wall plane master" + plane = WALL_PLANE + appearance_flags = PLANE_MASTER + +/obj/screen/plane_master/wall/backdrop(mob/mymob) + if(mymob?.client?.prefs.ambientocclusion) + add_filter("ambient_occlusion", 0, AMBIENT_OCCLUSION(4, "#04080FAA")) + else + remove_filter("ambient_occlusion") + +/obj/screen/plane_master/above_wall + name = "above wall plane master" + plane = ABOVE_WALL_PLANE + appearance_flags = PLANE_MASTER + +/obj/screen/plane_master/above_wall/Initialize() + . = ..() + add_filter("vision_cone", 100, list(type="alpha", render_source=FIELD_OF_VISION_RENDER_TARGET, flags=MASK_INVERSE)) + +/obj/screen/plane_master/above_wall/backdrop(mob/mymob) + if(mymob?.client?.prefs.ambientocclusion) + add_filter("ambient_occlusion", 0, AMBIENT_OCCLUSION(3, "#04080F64")) + else + remove_filter("ambient_occlusion") + ///Contains most things in the game world /obj/screen/plane_master/game_world name = "game world plane master" @@ -53,12 +83,50 @@ appearance_flags = PLANE_MASTER //should use client color blend_mode = BLEND_OVERLAY +/obj/screen/plane_master/game_world/Initialize() + . = ..() + add_filter("vision_cone", 100, list(type="alpha", render_source=FIELD_OF_VISION_RENDER_TARGET, flags=MASK_INVERSE)) + /obj/screen/plane_master/game_world/backdrop(mob/mymob) - if(istype(mymob) && mymob.client && mymob.client.prefs && mymob.client.prefs.ambientocclusion) - add_filter("ambient_occlusion", 0, AMBIENT_OCCLUSION) + if(mymob?.client?.prefs.ambientocclusion) + add_filter("ambient_occlusion", 0, AMBIENT_OCCLUSION(4, "#04080FAA")) else remove_filter("ambient_occlusion") - update_filters() + +//Reserved to chat messages, so they are still displayed above the field of vision masking. +/obj/screen/plane_master/chat_messages + name = "chat messages plane master" + plane = CHAT_PLANE + appearance_flags = PLANE_MASTER + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + +///Contains all shadow cone masks, whose image overrides are displayed only to their respective owners. +/obj/screen/plane_master/field_of_vision + name = "field of vision mask plane master" + plane = FIELD_OF_VISION_PLANE + render_target = FIELD_OF_VISION_RENDER_TARGET + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + +/obj/screen/plane_master/field_of_vision/Initialize() + . = ..() + filters += filter(type="alpha", render_source=FIELD_OF_VISION_BLOCKER_RENDER_TARGET, flags=MASK_INVERSE) + +///Used to display the owner and its adjacent surroundings through the FoV plane mask. +/obj/screen/plane_master/field_of_vision_blocker + name = "field of vision blocker plane master" + plane = FIELD_OF_VISION_BLOCKER_PLANE + render_target = FIELD_OF_VISION_BLOCKER_RENDER_TARGET + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + +///Stores the visible portion of the FoV shadow cone. +/obj/screen/plane_master/field_of_vision_visual + name = "field of vision visual plane master" + plane = FIELD_OF_VISION_VISUAL_PLANE + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + +/obj/screen/plane_master/field_of_vision_visual/Initialize() + . = ..() + filters += filter(type="alpha", render_source=FIELD_OF_VISION_BLOCKER_RENDER_TARGET, flags=MASK_INVERSE) ///Contains all lighting objects /obj/screen/plane_master/lighting @@ -87,11 +155,12 @@ /obj/screen/plane_master/emissive/Initialize() . = ..() filters += filter(type="alpha", render_source=EMISSIVE_BLOCKER_RENDER_TARGET, flags=MASK_INVERSE) + filters += filter(type="alpha", render_source=FIELD_OF_VISION_RENDER_TARGET, flags=MASK_INVERSE) /** * Things placed on this always mask the lighting plane. Doesn't render directly. * - * Always masks the light plane, isn't blocked by anything. Use for on mob glows, + * Always masks the light plane, isn't blocked by anything (except Field of Vision). Use for on mob glows, * magic stuff, etc. */ @@ -101,6 +170,10 @@ mouse_opacity = MOUSE_OPACITY_TRANSPARENT render_target = EMISSIVE_UNBLOCKABLE_RENDER_TARGET +/obj/screen/plane_master/emissive_unblockable/Initialize() + . = ..() + filters += filter(type="alpha", render_source=FIELD_OF_VISION_RENDER_TARGET, flags=MASK_INVERSE) + /** * Things placed on this layer mask the emissive layer. Doesn't render directly * diff --git a/code/_onclick/hud/radial.dm b/code/_onclick/hud/radial.dm index df91223ed1..1ead41d513 100644 --- a/code/_onclick/hud/radial.dm +++ b/code/_onclick/hud/radial.dm @@ -238,6 +238,7 @@ GLOBAL_LIST_EMPTY(radial_menus) var/mutable_appearance/MA = new /mutable_appearance(E) if(MA) MA.layer = ABOVE_HUD_LAYER + MA.plane = ABOVE_HUD_PLANE MA.appearance_flags |= RESET_TRANSFORM return MA @@ -255,6 +256,7 @@ GLOBAL_LIST_EMPTY(radial_menus) current_user = M.client //Blank menu_holder = image(icon='icons/effects/effects.dmi',loc=anchor,icon_state="nothing",layer = ABOVE_HUD_LAYER) + menu_holder.plane = ABOVE_HUD_PLANE menu_holder.appearance_flags |= KEEP_APART menu_holder.vis_contents += elements + close_button current_user.images += menu_holder @@ -285,13 +287,16 @@ GLOBAL_LIST_EMPTY(radial_menus) Choices should be a list where list keys are movables or text used for element names and return value and list values are movables/icons/images used for element icons */ -/proc/show_radial_menu(mob/user, atom/anchor, list/choices, uniqueid, radius, datum/callback/custom_check, require_near = FALSE, tooltips = FALSE) +/proc/show_radial_menu(mob/user, atom/anchor, list/choices, uniqueid, radius, datum/callback/custom_check, require_near = FALSE, tooltips = FALSE, no_repeat_close = FALSE) if(!user || !anchor || !length(choices)) return if(!uniqueid) uniqueid = "defmenu_[REF(user)]_[REF(anchor)]" if(GLOB.radial_menus[uniqueid]) + if(!no_repeat_close) + var/datum/radial_menu/menu = GLOB.radial_menus[uniqueid] + menu.finished = TRUE return var/datum/radial_menu/menu = new @@ -308,4 +313,9 @@ GLOBAL_LIST_EMPTY(radial_menus) var/answer = menu.selected_choice qdel(menu) GLOB.radial_menus -= uniqueid + if(require_near && !in_range(anchor, user)) + return + if(istype(custom_check)) + if(!custom_check.Invoke()) + return return answer \ No newline at end of file diff --git a/code/_onclick/hud/screen_objects/storage.dm b/code/_onclick/hud/screen_objects/storage.dm index bdcca70d9b..7e8bfe12ab 100644 --- a/code/_onclick/hud/screen_objects/storage.dm +++ b/code/_onclick/hud/screen_objects/storage.dm @@ -54,13 +54,18 @@ /obj/screen/storage/volumetric_box icon_state = "stored_continue" + layer = VOLUMETRIC_STORAGE_BOX_LAYER + plane = VOLUMETRIC_STORAGE_BOX_PLANE var/obj/item/our_item -/obj/screen/storage/volumetric_box/Initialize(mapload, new_master, our_item) +/obj/screen/storage/volumetric_box/Initialize(mapload, new_master, obj/item/our_item) src.our_item = our_item + RegisterSignal(our_item, COMSIG_ITEM_MOUSE_ENTER, .proc/on_item_mouse_enter) + RegisterSignal(our_item, COMSIG_ITEM_MOUSE_EXIT, .proc/on_item_mouse_exit) return ..() /obj/screen/storage/volumetric_box/Destroy() + makeItemInactive() our_item = null return ..() @@ -70,10 +75,34 @@ /obj/screen/storage/volumetric_box/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params) return our_item.MouseDrop(over, src_location, over_location, src_control, over_control, params) +/obj/screen/storage/volumetric_box/MouseExited(location, control, params) + makeItemInactive() + +/obj/screen/storage/volumetric_box/MouseEntered(location, control, params) + makeItemActive() + +/obj/screen/storage/volumetric_box/proc/on_item_mouse_enter() + makeItemActive() + +/obj/screen/storage/volumetric_box/proc/on_item_mouse_exit() + makeItemInactive() + +/obj/screen/storage/volumetric_box/proc/makeItemInactive() + if(!our_item) + return + our_item.layer = VOLUMETRIC_STORAGE_ITEM_LAYER + our_item.plane = VOLUMETRIC_STORAGE_ITEM_PLANE + +/obj/screen/storage/volumetric_box/proc/makeItemActive() + if(!our_item) + return + our_item.layer = VOLUMETRIC_STORAGE_ACTIVE_ITEM_LAYER //make sure we display infront of the others! + our_item.plane = VOLUMETRIC_STORAGE_ACTIVE_ITEM_PLANE + /obj/screen/storage/volumetric_box/center icon_state = "stored_continue" - var/obj/screen/storage/stored_left/left - var/obj/screen/storage/stored_right/right + var/obj/screen/storage/volumetric_edge/stored_left/left + var/obj/screen/storage/volumetric_edge/stored_right/right var/pixel_size /obj/screen/storage/volumetric_box/center/Initialize(mapload, new_master, our_item) @@ -87,7 +116,7 @@ return ..() /obj/screen/storage/volumetric_box/center/proc/on_screen_objects() - return list(src, left, right) + return list(src) /** * Sets the size of this box screen object and regenerates its left/right borders. This includes the actual border's size! @@ -96,18 +125,38 @@ if(pixel_size == pixels) return pixel_size = pixels - cut_overlays() + cut_overlays(TRUE) //our icon size is 32 pixels. transform = matrix((pixels - (VOLUMETRIC_STORAGE_BOX_BORDER_SIZE * 2)) / VOLUMETRIC_STORAGE_BOX_ICON_SIZE, 0, 0, 0, 1, 0) left.pixel_x = -((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) - VOLUMETRIC_STORAGE_BOX_BORDER_SIZE right.pixel_x = ((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) + VOLUMETRIC_STORAGE_BOX_BORDER_SIZE - add_overlay(left) - add_overlay(right) + add_overlay(left, TRUE) + add_overlay(right, TRUE) -/obj/screen/storage/stored_left +/obj/screen/storage/volumetric_edge + layer = VOLUMETRIC_STORAGE_BOX_LAYER + plane = VOLUMETRIC_STORAGE_BOX_PLANE + +/obj/screen/storage/volumetric_edge/Initialize(mapload, master, our_item) + src.master = master + return ..() + +/obj/screen/storage/volumetric_edge/Click(location, control, params) + return master.Click(location, control, params) + +/obj/screen/storage/volumetric_edge/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params) + return master.MouseDrop(over, src_location, over_location, src_control, over_control, params) + +/obj/screen/storage/volumetric_edge/MouseExited(location, control, params) + return master.MouseExited(location, control, params) + +/obj/screen/storage/volumetric_edge/MouseEntered(location, control, params) + return master.MouseEntered(location, control, params) + +/obj/screen/storage/volumetric_edge/stored_left icon_state = "stored_start" appearance_flags = APPEARANCE_UI | KEEP_APART | RESET_TRANSFORM // Yes I know RESET_TRANSFORM is in APPEARANCE_UI but we're hard-asserting this incase someone changes it. -/obj/screen/storage/stored_right +/obj/screen/storage/volumetric_edge/stored_right icon_state = "stored_end" appearance_flags = APPEARANCE_UI | KEEP_APART | RESET_TRANSFORM diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index f0e4a0ea08..efb2094291 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -91,7 +91,7 @@ log_combat(user, M, "attacked", src.name, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])") add_fingerprint(user) - user.adjustStaminaLossBuffered(getweight()*0.8)//CIT CHANGE - makes attacking things cause stamina loss + user.adjustStaminaLossBuffered(getweight(user, STAM_COST_ATTACK_MOB_MULT))//CIT CHANGE - makes attacking things cause stamina loss //the equivalent of the standard version of attack() but for object targets. /obj/item/proc/attack_obj(obj/O, mob/living/user) @@ -102,7 +102,7 @@ if(IS_STAMCRIT(user)) // CIT CHANGE - makes it impossible to attack in stamina softcrit to_chat(user, "You're too exhausted.") // CIT CHANGE - ditto return // CIT CHANGE - ditto - user.adjustStaminaLossBuffered(getweight()*1.2)//CIT CHANGE - makes attacking things cause stamina loss + user.adjustStaminaLossBuffered(getweight(user, STAM_COST_ATTACK_OBJ_MULT))//CIT CHANGE - makes attacking things cause stamina loss user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(O) O.attacked_by(src, user) @@ -111,28 +111,34 @@ return /obj/attacked_by(obj/item/I, mob/living/user) - if(I.force) + var/totitemdamage = I.force + var/bad_trait + if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && iscarbon(user)) + totitemdamage *= 0.5 + bad_trait = SKILL_COMBAT_MODE //blacklist combat skills. + if(I.used_skills && user.mind) + if(totitemdamage) + totitemdamage = user.mind.item_action_skills_mod(I, totitemdamage, I.skill_difficulty, SKILL_ATTACK_OBJ, bad_trait) + for(var/skill in I.used_skills) + if(!(I.used_skills[skill] & SKILL_TRAIN_ATTACK_OBJ)) + continue + user.mind.auto_gain_experience(skill, I.skill_gain) + if(totitemdamage) visible_message("[user] has hit [src] with [I]!", null, null, COMBAT_MESSAGE_RANGE) //only witnesses close by and the victim see a hit message. log_combat(user, src, "attacked", I) - take_damage(I.force, I.damtype, "melee", 1) + take_damage(totitemdamage, I.damtype, "melee", 1) /mob/living/attacked_by(obj/item/I, mob/living/user) - //CIT CHANGES START HERE - combatmode and resting checks - var/totitemdamage = I.force - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - totitemdamage *= 0.5 - if(!CHECK_MOBILITY(user, MOBILITY_STAND)) - totitemdamage *= 0.5 - //CIT CHANGES END HERE var/list/block_return = list() - if((user != src) && run_block(I, totitemdamage, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, return_list = block_return) & BLOCK_SUCCESS) + var/totitemdamage = pre_attacked_by(I, user) + if((user != src) && mob_run_block(I, totitemdamage, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, null, block_return) & BLOCK_SUCCESS) return FALSE totitemdamage = block_calculate_resultant_damage(totitemdamage, block_return) send_item_attack_message(I, user) - I.do_stagger_action(src, user) + I.do_stagger_action(src, user, totitemdamage) if(I.force) - apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage + apply_damage(totitemdamage, I.damtype) if(I.damtype == BRUTE) if(prob(33)) I.add_mob_blood(src) @@ -148,6 +154,28 @@ else return ..() +/mob/living/proc/pre_attacked_by(obj/item/I, mob/living/user) + . = I.force + var/bad_trait + if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && iscarbon(user)) + . *= 0.5 + bad_trait = SKILL_COMBAT_MODE //blacklist combat skills. + if(!CHECK_MOBILITY(user, MOBILITY_STAND)) + . *= 0.5 + if(!user.mind || !I.used_skills) + return + if(.) + . = user.mind.item_action_skills_mod(I, ., I.skill_difficulty, SKILL_ATTACK_MOB, bad_trait) + for(var/skill in I.used_skills) + if(!(I.used_skills[skill] & SKILL_TRAIN_ATTACK_MOB)) + continue + user.mind.auto_gain_experience(skill, I.skill_gain) + +/mob/living/carbon/pre_attacked_by(obj/item/I, mob/living/user) + . = ..() + if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + . *= 1.5 + // Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person. // Click parameters is the params string from byond Click() code, see that documentation. /obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters) @@ -181,22 +209,30 @@ return 1 /// How much stamina this takes to swing this is not for realism purposes hecc off. -/obj/item/proc/getweight() - return total_mass || w_class * 1.25 +/obj/item/proc/getweight(mob/living/user, multiplier = 1, trait = SKILL_STAMINA_COST) + . = (total_mass || w_class * STAM_COST_W_CLASS_MULT) * multiplier + if(!user) + return + var/bad_trait + if(iscarbon(user) && !(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + . *= STAM_COST_NO_COMBAT_MULT + bad_trait = SKILL_COMBAT_MODE + if(used_skills && user.mind) + . = user.mind.item_action_skills_mod(src, ., skill_difficulty, trait, bad_trait, FALSE) /// How long this staggers for. 0 and negatives supported. -/obj/item/proc/melee_stagger_duration() +/obj/item/proc/melee_stagger_duration(force_override) if(!isnull(stagger_force)) return stagger_force /// totally not an untested, arbitrary equation. - return clamp((1.5 + (w_class/7.5)) * (force / 2), 0, 10 SECONDS) + return clamp((1.5 + (w_class/7.5)) * ((force_override || force) / 2), 0, 10 SECONDS) -/obj/item/proc/do_stagger_action(mob/living/target, mob/living/user) +/obj/item/proc/do_stagger_action(mob/living/target, mob/living/user, force_override) if(!CHECK_BITFIELD(target.status_flags, CANSTAGGER)) return FALSE if(target.combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) target.do_staggered_animation() - var/duration = melee_stagger_duration() + var/duration = melee_stagger_duration(force_override) if(!duration) //0 return FALSE else if(duration > 0) diff --git a/code/controllers/admin.dm b/code/controllers/admin.dm index 19fef28597..28803f0979 100644 --- a/code/controllers/admin.dm +++ b/code/controllers/admin.dm @@ -3,9 +3,7 @@ name = "Initializing..." var/target -INITIALIZE_IMMEDIATE(/obj/effect/statclick) - -/obj/effect/statclick/Initialize(mapload, text, target) //Don't port this to Initialize it's too critical +/obj/effect/statclick/New(loc, text, target) //Don't port this to Initialize it's too critical . = ..() name = text src.target = target @@ -33,6 +31,14 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick) usr.client.debug_variables(target) message_admins("Admin [key_name_admin(usr)] is debugging the [target] [class].") +/obj/effect/statclick/misc_subsystems/Click() + if(!usr.client.holder) + return + var/subsystem = input(usr, "Debug which subsystem?", "Debug nonprocessing subsystem") as null|anything in (Master.subsystems - Master.statworthy_subsystems) + if(!subsystem) + return + usr.client.debug_variables(subsystem) + message_admins("Admin [key_name_admin(usr)] is debugging the [subsystem] subsystem.") // Debug verbs. /client/proc/restart_controller(controller in list("Master", "Failsafe")) diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 2c317ade2a..79b110a78a 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -35,6 +35,13 @@ /datum/config_entry/keyed_list/midround_antag/ValidateListEntry(key_name, key_value) return key_name in config.modes +/datum/config_entry/keyed_list/force_antag_count + key_mode = KEY_MODE_TEXT + value_mode = VALUE_MODE_FLAG + +/datum/config_entry/keyed_list/force_antag_count/ValidateListEntry(key_name, key_value) + return key_name in config.modes + /datum/config_entry/keyed_list/policy key_mode = KEY_MODE_TEXT value_mode = VALUE_MODE_TEXT @@ -74,6 +81,8 @@ /datum/config_entry/flag/disable_peaceborg +/datum/config_entry/flag/economy //money money money money money money money money money money money money + /datum/config_entry/number/minimum_secborg_alert //Minimum alert level for secborgs to be chosen. config_entry_value = 3 @@ -498,3 +507,13 @@ //Allows players to set a hexadecimal color of their choice as skin tone, on top of the standard ones. /datum/config_entry/flag/allow_custom_skintones + +///Initial loadout points +/datum/config_entry/number/initial_gear_points + config_entry_value = 10 + +/** + * Enables the FoV component, which hides objects and mobs behind the parent from their sight, unless they turn around, duh. + * Camera mobs, AIs, ghosts and some other are of course exempt from this. This also doesn't influence simplemob AI, for the best. + */ +/datum/config_entry/flag/use_field_of_vision diff --git a/code/controllers/master.dm b/code/controllers/master.dm index db828539af..cdbea1de85 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -28,6 +28,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new // List of subsystems to process(). var/list/subsystems + /// List of subsystems to include in the MC stat panel. + var/list/statworthy_subsystems // Vars for keeping track of tick drift. var/init_timeofday @@ -65,6 +67,9 @@ GLOBAL_REAL(Master, /datum/controller/master) = new //used by CHECK_TICK as well so that the procs subsystems call can obey that SS's tick limits var/static/current_ticklimit = TICK_LIMIT_RUNNING + /// Statclick for misc subsystems + var/obj/effect/statclick/misc_subsystems/misc_statclick + /datum/controller/master/New() if(!config) config = new @@ -87,6 +92,11 @@ GLOBAL_REAL(Master, /datum/controller/master) = new _subsystems += new I Master = src + // We want to see all subsystems during init. + statworthy_subsystems = subsystems.Copy() + + misc_statclick = new(null, "Debug") + if(!GLOB) new /datum/controller/global_vars @@ -257,10 +267,14 @@ GLOBAL_REAL(Master, /datum/controller/master) = new var/list/tickersubsystems = list() var/list/runlevel_sorted_subsystems = list(list()) //ensure we always have at least one runlevel var/timer = world.time + statworthy_subsystems = list() for (var/thing in subsystems) var/datum/controller/subsystem/SS = thing if (SS.flags & SS_NO_FIRE) + if(SS.flags & SS_ALWAYS_SHOW_STAT) + statworthy_subsystems += SS continue + statworthy_subsystems += SS SS.queued_time = 0 SS.queue_next = null SS.queue_prev = null @@ -603,7 +617,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new stat("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)") stat("Master Controller:", statclick.update("(TickRate:[Master.processing]) (Iteration:[Master.iteration]) (TickLimit: [round(Master.current_ticklimit, 0.1)])")) - + stat("Misc Subsystems", misc_statclick) /datum/controller/master/StartLoadingMap() //disallow more than one map to load at once, multithreading it will just cause race conditions diff --git a/code/controllers/subsystem/economy.dm b/code/controllers/subsystem/economy.dm new file mode 100644 index 0000000000..078d122aa6 --- /dev/null +++ b/code/controllers/subsystem/economy.dm @@ -0,0 +1,139 @@ +SUBSYSTEM_DEF(economy) + name = "Economy" + wait = 5 MINUTES + init_order = INIT_ORDER_ECONOMY + runlevels = RUNLEVEL_GAME + var/roundstart_paychecks = 5 + var/budget_pool = 35000 + var/list/department_accounts = list(ACCOUNT_CIV = ACCOUNT_CIV_NAME, + ACCOUNT_ENG = ACCOUNT_ENG_NAME, + ACCOUNT_SCI = ACCOUNT_SCI_NAME, + ACCOUNT_MED = ACCOUNT_MED_NAME, + ACCOUNT_SRV = ACCOUNT_SRV_NAME, + ACCOUNT_CAR = ACCOUNT_CAR_NAME, + ACCOUNT_SEC = ACCOUNT_SEC_NAME) + var/list/generated_accounts = list() + var/full_ancap = FALSE // Enables extra money charges for things that normally would be free, such as sleepers/cryo/cloning. + //Take care when enabling, as players will NOT respond well if the economy is set up for low cash flows. + var/alive_humans_bounty = 100 + var/crew_safety_bounty = 1500 + var/monster_bounty = 150 + var/mood_bounty = 100 + var/techweb_bounty = 250 + var/slime_bounty = list("grey" = 10, + // tier 1 + "orange" = 100, + "metal" = 100, + "blue" = 100, + "purple" = 100, + // tier 2 + "dark purple" = 500, + "dark blue" = 500, + "green" = 500, + "silver" = 500, + "gold" = 500, + "yellow" = 500, + "red" = 500, + "pink" = 500, + // tier 3 + "cerulean" = 750, + "sepia" = 750, + "bluespace" = 750, + "pyrite" = 750, + "light pink" = 750, + "oil" = 750, + "adamantine" = 750, + // tier 4 + "rainbow" = 1000) + var/list/bank_accounts = list() //List of normal accounts (not department accounts) + var/list/dep_cards = list() + +/datum/controller/subsystem/economy/Initialize(timeofday) + var/budget_to_hand_out = round(budget_pool / department_accounts.len) + for(var/A in department_accounts) + new /datum/bank_account/department(A, budget_to_hand_out) + return ..() + +/datum/controller/subsystem/economy/fire(resumed = 0) + eng_payout() // Payout based on nothing. What will replace it? Surplus power, powered APC's, air alarms? Who knows. + sci_payout() // Payout based on slimes. + secmedsrv_payout() // Payout based on crew safety, health, and mood. + civ_payout() // Payout based on ??? Profit + car_payout() // Cargo's natural gain in the cash moneys. + for(var/A in bank_accounts) + var/datum/bank_account/B = A + B.payday(1) + + +/datum/controller/subsystem/economy/proc/get_dep_account(dep_id) + for(var/datum/bank_account/department/D in generated_accounts) + if(D.department_id == dep_id) + return D + +/datum/controller/subsystem/economy/proc/eng_payout() + var/engineering_cash = 3000 + var/datum/bank_account/D = get_dep_account(ACCOUNT_ENG) + if(D) + D.adjust_money(engineering_cash) + + +/datum/controller/subsystem/economy/proc/car_payout() + var/cargo_cash = 500 + var/datum/bank_account/D = get_dep_account(ACCOUNT_CAR) + if(D) + D.adjust_money(cargo_cash) + +/datum/controller/subsystem/economy/proc/secmedsrv_payout() + var/crew + var/alive_crew + var/dead_monsters + var/cash_to_grant + for(var/mob/m in GLOB.mob_list) + if(isnewplayer(m)) + continue + if(m.mind) + if(isbrain(m) || iscameramob(m)) + continue + if(ishuman(m)) + var/mob/living/carbon/human/H = m + crew++ + if(H.stat != DEAD) + alive_crew++ + var/datum/component/mood/mood = H.GetComponent(/datum/component/mood) + var/medical_cash = (H.health / H.maxHealth) * alive_humans_bounty + if(mood) + var/datum/bank_account/D = get_dep_account(ACCOUNT_SRV) + if(D) + var/mood_dosh = (mood.mood_level / 9) * mood_bounty + D.adjust_money(mood_dosh) + medical_cash *= (mood.sanity / 100) + + var/datum/bank_account/D = get_dep_account(ACCOUNT_MED) + if(D) + D.adjust_money(medical_cash) + if(ishostile(m)) + var/mob/living/simple_animal/hostile/H = m + if(H.stat == DEAD && (H.z in SSmapping.levels_by_trait(ZTRAIT_STATION))) + dead_monsters++ + CHECK_TICK + var/living_ratio = alive_crew / crew + cash_to_grant = (crew_safety_bounty * living_ratio) + (monster_bounty * dead_monsters) + var/datum/bank_account/D = get_dep_account(ACCOUNT_SEC) + if(D) + D.adjust_money(min(cash_to_grant, MAX_GRANT_SECMEDSRV)) + +/datum/controller/subsystem/economy/proc/sci_payout() + var/science_bounty = 0 + for(var/mob/living/simple_animal/slime/S in GLOB.mob_list) + if(S.stat == DEAD) + continue + science_bounty += slime_bounty[S.colour] + var/datum/bank_account/D = get_dep_account(ACCOUNT_SCI) + if(D) + D.adjust_money(min(science_bounty, MAX_GRANT_SCI)) + +/datum/controller/subsystem/economy/proc/civ_payout() + var/civ_cash = (rand(1,5) * 500) + var/datum/bank_account/D = get_dep_account(ACCOUNT_CIV) + if(D) + D.adjust_money(min(civ_cash, MAX_GRANT_CIV)) diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 166f930e33..8a1c08bc35 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -451,3 +451,18 @@ SUBSYSTEM_DEF(garbage) #endif #endif + +#ifdef TESTING +/proc/writeDatumCount() + var/list/datums = list() + for(var/datum/D in world) + datums[D.type] += 1 + for(var/datum/D) + datums[D.type] += 1 + datums = sortTim(datums, /proc/cmp_numeric_dsc, associative = TRUE) + if(fexists("data/DATUMCOUNT.txt")) + fdel("data/DATUMCOUNT.txt") + var/outfile = file("data/DATUMCOUNT.txt") + for(var/path in datums) + outfile << "[datums[path]]\t\t\t\t\t[path]" +#endif diff --git a/code/controllers/subsystem/input.dm b/code/controllers/subsystem/input.dm index 0970b23a16..7c51ba4506 100644 --- a/code/controllers/subsystem/input.dm +++ b/code/controllers/subsystem/input.dm @@ -6,13 +6,20 @@ SUBSYSTEM_DEF(input) priority = FIRE_PRIORITY_INPUT runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY - var/list/macro_sets - var/list/movement_keys + /// Classic mode input focused macro set. Manually set because we can't define ANY or ANY+UP for classic. + var/static/list/macroset_classic_input + /// Classic mode map focused macro set. Manually set because it needs to be clientside and go to macroset_classic_input. + var/static/list/macroset_classic_hotkey + /// New hotkey mode macro set. All input goes into map, game keeps incessently setting your focus to map, we can use ANY all we want here; we don't care about the input bar, the user has to force the input bar every time they want to type. + var/static/list/macroset_hotkey + + /// Macro set for hotkeys + var/list/hotkey_mode_macros + /// Macro set for classic. + var/list/input_mode_macros /datum/controller/subsystem/input/Initialize() - setup_default_macro_sets() - - setup_default_movement_keys() + setup_macrosets() initialized = TRUE @@ -20,90 +27,69 @@ SUBSYSTEM_DEF(input) return ..() -// This is for when macro sets are eventualy datumized -/datum/controller/subsystem/input/proc/setup_default_macro_sets() - var/list/static/default_macro_sets - - if(default_macro_sets) - macro_sets = default_macro_sets - return - - default_macro_sets = list( - "default" = list( - "Tab" = "\".winset \\\"input.focus=true?map.focus=true input.background-color=[COLOR_INPUT_DISABLED]:input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"", - "O" = "ooc", - "Ctrl+O" = "looc", - "T" = "say", - "Ctrl+T" = "whisper", - "M" = "me", - "Ctrl+M" = "subtle", - "Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs - "Any" = "\"KeyDown \[\[*\]\]\"", - "Any+UP" = "\"KeyUp \[\[*\]\]\"", - ), - "old_default" = list( - "Tab" = "\".winset \\\"mainwindow.macro=old_hotkeys map.focus=true input.background-color=[COLOR_INPUT_DISABLED]\\\"\"", - "Ctrl+T" = "say", - "Ctrl+O" = "ooc", - ), - "old_hotkeys" = list( - "Tab" = "\".winset \\\"mainwindow.macro=old_default input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"", - "O" = "ooc", - "L" = "looc", - "T" = "say", - "M" = "me", - "Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs - "Any" = "\"KeyDown \[\[*\]\]\"", - "Any+UP" = "\"KeyUp \[\[*\]\]\"", - ), - ) - - // Because i'm lazy and don't want to type all these out twice - var/list/old_default = default_macro_sets["old_default"] - - var/list/static/oldmode_keys = list( +/// Sets up the key list for classic mode for when badmins screw up vv's. +/datum/controller/subsystem/input/proc/setup_macrosets() + // First, let's do the snowflake keyset! + macroset_classic_input = list() + var/list/classic_mode_keys = list( "North", "East", "South", "West", "Northeast", "Southeast", "Northwest", "Southwest", - "Insert", "Delete", "Ctrl", "Alt", + "Insert", "Delete", "Ctrl", "Alt", "Shift", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", ) + for(var/key in classic_mode_keys) + macroset_classic_input[key] = "\"KeyDown [key]\"" + macroset_classic_input["[key]+UP"] = "\"KeyUp [key]\"" + // LET'S PLAY THE BIND EVERY KEY GAME! + // oh except for Backspace and Enter; if you want to use those you shouldn't have used oldmode! + var/list/classic_ctrl_override_keys = list( + "\[", "\]", "\\\\", ";", "'", ",", ".", "/", "-", "=", "`" + ) + // i'm lazy let's play the list iteration game of numbers + for(var/i in 0 to 9) + classic_ctrl_override_keys += "[i]" + // let's play the ascii game of A to Z (UPPERCASE) + for(var/i in 65 to 90) + classic_ctrl_override_keys += ascii2text(i) + // let's play the game of clientside bind overrides! + classic_ctrl_override_keys -= list("T", "O", "M", "L") + macroset_classic_input["Ctrl+T"] = "say" + macroset_classic_input["Ctrl+O"] = "ooc" + macroset_classic_input["Ctrl+L"] = "looc" + // let's play the list iteration game x2 + for(var/key in classic_ctrl_override_keys) + // make sure to double double quote to ensure things are treated as a key combo instead of addition/semicolon logic. + macroset_classic_input["\"Ctrl+[key]\""] = "\"KeyDown [istext(classic_ctrl_override_keys[key])? classic_ctrl_override_keys[key] : key]\"" + macroset_classic_input["\"Ctrl+[key]+UP\""] = "\"KeyUp [istext(classic_ctrl_override_keys[key])? classic_ctrl_override_keys[key] : key]\"" + // Misc + macroset_classic_input["Tab"] = "\".winset \\\"mainwindow.macro=[SKIN_MACROSET_CLASSIC_HOTKEYS] map.focus=true input.background-color=[COLOR_INPUT_DISABLED]\\\"\"" + macroset_classic_input["Escape"] = "\".winset \\\"input.text=\\\"\\\"\\\"\"" - for(var/i in 1 to oldmode_keys.len) - var/key = oldmode_keys[i] - old_default[key] = "\"KeyDown [key]\"" - old_default["[key]+UP"] = "\"KeyUp [key]\"" + // FINALLY, WE CAN DO SOMETHING MORE NORMAL FOR THE SNOWFLAKE-BUT-LESS KEYSET. + macroset_classic_hotkey = list( + "Any" = "\"KeyDown \[\[*\]\]\"", + "Any+UP" = "\"KeyUp \[\[*\]\]\"", + "Tab" = "\".winset \\\"mainwindow.macro=[SKIN_MACROSET_CLASSIC_INPUT] input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"", + "Escape" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", + "Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", + "O" = "ooc", + "T" = "say", + "L" = "looc", + "M" = "me" + ) - var/list/static/oldmode_ctrl_override_keys = list( - "W" = "W", "A" = "A", "S" = "S", "D" = "D", // movement - "1" = "1", "2" = "2", "3" = "3", "4" = "4", // intent - "B" = "B", // resist - "E" = "E", // quick equip - "F" = "F", // intent left - "G" = "G", // intent right - "H" = "H", // stop pulling - "Q" = "Q", // drop - "R" = "R", // throw - "X" = "X", // switch hands - "Y" = "Y", // activate item - "Z" = "Z", // activate item - ) - - for(var/i in 1 to oldmode_ctrl_override_keys.len) - var/key = oldmode_ctrl_override_keys[i] - var/override = oldmode_ctrl_override_keys[key] - old_default["Ctrl+[key]"] = "\"KeyDown [override]\"" - old_default["Ctrl+[key]+UP"] = "\"KeyUp [override]\"" - - macro_sets = default_macro_sets - -// For initially setting up or resetting to default the movement keys -/datum/controller/subsystem/input/proc/setup_default_movement_keys() - var/static/list/default_movement_keys = list( - "W" = NORTH, "A" = WEST, "S" = SOUTH, "D" = EAST, // WASD - "North" = NORTH, "West" = WEST, "South" = SOUTH, "East" = EAST, // Arrow keys & Numpad - ) - - movement_keys = default_movement_keys.Copy() + // And finally, the modern set. + macroset_hotkey = list( + "Any" = "\"KeyDown \[\[*\]\]\"", + "Any+UP" = "\"KeyUp \[\[*\]\]\"", + "Tab" = "\".winset \\\"input.focus=true?map.focus=true input.background-color=[COLOR_INPUT_DISABLED]:input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"", + "Escape" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", + "Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", + "O" = "ooc", + "T" = "say", + "L" = "looc", + "M" = "me" + ) // Badmins just wanna have fun ♪ /datum/controller/subsystem/input/proc/refresh_client_macro_sets() @@ -111,9 +97,10 @@ SUBSYSTEM_DEF(input) for(var/i in 1 to clients.len) var/client/user = clients[i] user.set_macros() + user.update_movement_keys() /datum/controller/subsystem/input/fire() var/list/clients = GLOB.clients // Let's sing the list cache song - for(var/i in 1 to length(clients)) + for(var/i in 1 to clients.len) var/client/C = clients[i] C.keyLoop() diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 7c48adef24..4b2cf24f1e 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -479,6 +479,10 @@ SUBSYSTEM_DEF(job) to_chat(M, "[job.custom_spawn_text]") if(CONFIG_GET(number/minimal_access_threshold)) to_chat(M, "As this station was initially staffed with a [CONFIG_GET(flag/jobs_have_minimal_access) ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] have been added to your ID card.") + if(ishuman(H)) + var/mob/living/carbon/human/wageslave = H + to_chat(M, "Your account ID is [wageslave.account_id].") + H.add_memory("Your account ID is [wageslave.account_id].") if(job && H) if(job.dresscodecompliant)// CIT CHANGE - dress code compliance equip_loadout(N, H) // CIT CHANGE - allows players to spawn with loadout items diff --git a/code/controllers/subsystem/moods.dm b/code/controllers/subsystem/moods.dm deleted file mode 100644 index f6b6ffcb40..0000000000 --- a/code/controllers/subsystem/moods.dm +++ /dev/null @@ -1,4 +0,0 @@ -PROCESSING_SUBSYSTEM_DEF(mood) - name = "Mood" - flags = SS_NO_INIT | SS_BACKGROUND - priority = 20 diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm index 0a60c6e5d3..cd577e4ac6 100644 --- a/code/controllers/subsystem/persistence.dm +++ b/code/controllers/subsystem/persistence.dm @@ -24,6 +24,8 @@ SUBSYSTEM_DEF(persistence) var/list/saved_votes = list() var/list/obj/structure/sign/picture_frame/photo_frames var/list/obj/item/storage/photo_album/photo_albums + var/list/obj/structure/sign/painting/painting_frames = list() + var/list/paintings = list() /datum/controller/subsystem/persistence/Initialize() LoadSatchels() @@ -265,6 +267,7 @@ SUBSYSTEM_DEF(persistence) CollectAntagReputation() SaveRandomizedRecipes() SavePanicBunker() + SavePaintings() /datum/controller/subsystem/persistence/proc/LoadPanicBunker() var/bunker_path = file("data/bunker_passthrough.json") @@ -528,3 +531,19 @@ SUBSYSTEM_DEF(persistence) file_data["data"] = saved_votes[ckey] fdel(json_file) WRITE_FILE(json_file, json_encode(file_data)) + +/datum/controller/subsystem/persistence/proc/LoadPaintings() + var/json_file = file("data/paintings.json") + if(fexists(json_file)) + paintings = json_decode(file2text(json_file)) + + for(var/obj/structure/sign/painting/P in painting_frames) + P.load_persistent() + +/datum/controller/subsystem/persistence/proc/SavePaintings() + for(var/obj/structure/sign/painting/P in painting_frames) + P.save_persistent() + + var/json_file = file("data/paintings.json") + fdel(json_file) + WRITE_FILE(json_file, json_encode(paintings)) diff --git a/code/controllers/subsystem/processing/projectiles.dm b/code/controllers/subsystem/processing/projectiles.dm index 8cd63c6949..b8d904c727 100644 --- a/code/controllers/subsystem/processing/projectiles.dm +++ b/code/controllers/subsystem/processing/projectiles.dm @@ -1,21 +1,22 @@ PROCESSING_SUBSYSTEM_DEF(projectiles) name = "Projectiles" + priority = FIRE_PRIORITY_PROJECTILES wait = 1 stat_tag = "PP" flags = SS_NO_INIT|SS_TICKER - var/global_pixel_speed = 2 - var/global_iterations_per_move = 16 + var/global_pixel_increment_amount = 4 + var/global_projectile_speed_multiplier = 1 /datum/controller/subsystem/processing/projectiles/proc/set_pixel_speed(new_speed) - global_pixel_speed = new_speed + global_pixel_increment_amount = new_speed for(var/i in processing) var/obj/item/projectile/P = i if(istype(P)) //there's non projectiles on this too. - P.set_pixel_speed(new_speed) + P.set_pixel_increment_amount(new_speed) /datum/controller/subsystem/processing/projectiles/vv_edit_var(var_name, var_value) switch(var_name) - if(NAMEOF(src, global_pixel_speed)) + if(NAMEOF(src, global_pixel_increment_amount)) set_pixel_speed(var_value) return TRUE else diff --git a/code/controllers/subsystem/research.dm b/code/controllers/subsystem/research.dm index f158574763..d816e37ddf 100644 --- a/code/controllers/subsystem/research.dm +++ b/code/controllers/subsystem/research.dm @@ -24,6 +24,7 @@ SUBSYSTEM_DEF(research) var/list/techweb_categories = list() //category name = list(node.id = TRUE) var/list/techweb_boost_items = list() //associative double-layer path = list(id = list(point_type = point_discount)) var/list/techweb_nodes_hidden = list() //Node ids that should be hidden by default. + var/list/techweb_nodes_experimental = list() //Node ids that are exclusive to the BEPIS. var/list/techweb_point_items = list( //path = list(point type = value) /obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 10000), @@ -508,6 +509,8 @@ SUBSYSTEM_DEF(research) D.unlocked_by += node.id if(node.hidden) techweb_nodes_hidden[node.id] = TRUE + if(node.experimental) + techweb_nodes_experimental[node.id] = TRUE CHECK_TICK generate_techweb_unlock_linking() diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index a3e804d541..532eb19bc9 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -35,10 +35,8 @@ SUBSYSTEM_DEF(shuttle) //supply shuttle stuff var/obj/docking_port/mobile/supply/supply var/ordernum = 1 //order number given to next order - var/points = 5000 //number of trade-points we have var/centcom_message = "" //Remarks from CentCom on how well you checked the last order. var/list/discoveredPlants = list() //Typepaths for unusual plants we've already sent CentCom, associated with their potencies - var/passive_supply_points_per_minute = 125 var/list/supply_packs = list() var/list/shoppinglist = list() @@ -113,9 +111,6 @@ SUBSYSTEM_DEF(shuttle) qdel(T, force=TRUE) CheckAutoEvac() - if(!(times_fired % CEILING(600/wait, 1))) - points += passive_supply_points_per_minute - var/esETA = emergency?.getModeStr() emergency_shuttle_stat_text = "[esETA? "[esETA] [emergency.getTimerStr()]" : ""]" @@ -559,7 +554,6 @@ SUBSYSTEM_DEF(shuttle) centcom_message = SSshuttle.centcom_message ordernum = SSshuttle.ordernum - points = SSshuttle.points emergencyNoEscape = SSshuttle.emergencyNoEscape emergencyCallAmount = SSshuttle.emergencyCallAmount shuttle_purchased = SSshuttle.shuttle_purchased diff --git a/code/datums/action.dm b/code/datums/action.dm index 8862482dc2..00e7e0ad5d 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -186,6 +186,8 @@ /datum/action/item_action/New(Target) ..() + if(button_icon_state) + use_target_appearance = FALSE var/obj/item/I = target LAZYINITLIST(I.actions) I.actions += src @@ -345,6 +347,7 @@ /datum/action/item_action/clock/quickbind name = "Quickbind" desc = "If you're seeing this, file a bug report." + use_target_appearance = FALSE var/scripture_index = 0 //the index of the scripture we're associated with /datum/action/item_action/toggle_helmet_flashlight diff --git a/code/datums/actions/ninja.dm b/code/datums/actions/ninja.dm index b655078349..c0314b9c48 100644 --- a/code/datums/actions/ninja.dm +++ b/code/datums/actions/ninja.dm @@ -8,11 +8,11 @@ icon_icon = 'icons/mob/actions/actions_spells.dmi' /datum/action/item_action/ninjaboost - check_flags = NONE name = "Adrenaline Boost" desc = "Inject a secret chemical that will counteract all movement-impairing effect." button_icon_state = "repulse" icon_icon = 'icons/mob/actions/actions_spells.dmi' + required_mobility_flags = NONE /datum/action/item_action/ninjapulse name = "EM Burst (25E)" diff --git a/code/datums/brain_damage/hypnosis.dm b/code/datums/brain_damage/hypnosis.dm index 37aee6df7e..f4c4541db9 100644 --- a/code/datums/brain_damage/hypnosis.dm +++ b/code/datums/brain_damage/hypnosis.dm @@ -63,7 +63,7 @@ if(prob(2)) switch(rand(1,2)) if(1) - to_chat(owner, "...[lowertext(hypnotic_phrase)]...") + to_chat(owner, "...[lowertext(hypnotic_phrase)]...") if(2) new /datum/hallucination/chat(owner, TRUE, FALSE, "[hypnotic_phrase]") diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm index 3f71d192e3..e5e1434ab8 100644 --- a/code/datums/brain_damage/imaginary_friend.dm +++ b/code/datums/brain_damage/imaginary_friend.dm @@ -91,7 +91,6 @@ trauma = _trauma owner = trauma.owner - copy_known_languages_from(owner, TRUE) setup_friend() diff --git a/code/datums/brain_damage/phobia.dm b/code/datums/brain_damage/phobia.dm index 80a1bd2470..279118d877 100644 --- a/code/datums/brain_damage/phobia.dm +++ b/code/datums/brain_damage/phobia.dm @@ -44,7 +44,7 @@ return if(world.time > next_check && world.time > next_scare) next_check = world.time + 50 - var/list/seen_atoms = view(7, owner) + var/list/seen_atoms = owner.fov_view(7) if(LAZYLEN(trigger_objs)) for(var/obj/O in seen_atoms) diff --git a/code/datums/brain_damage/severe.dm b/code/datums/brain_damage/severe.dm index 0e08c4cd15..bb37129b95 100644 --- a/code/datums/brain_damage/severe.dm +++ b/code/datums/brain_damage/severe.dm @@ -26,21 +26,15 @@ scan_desc = "extensive damage to the brain's language center" gain_text = "You have trouble forming words in your head..." lose_text = "You suddenly remember how languages work." - var/datum/language_holder/prev_language - var/datum/language_holder/mob_language /datum/brain_trauma/severe/aphasia/on_gain() - mob_language = owner.get_language_holder() - prev_language = mob_language.copy() - mob_language.remove_all_languages() - mob_language.grant_language(/datum/language/aphasia) + owner.add_blocked_language(subtypesof(/datum/language/) - /datum/language/aphasia, LANGUAGE_APHASIA) + owner.grant_language(/datum/language/aphasia, TRUE, TRUE, LANGUAGE_APHASIA) ..() /datum/brain_trauma/severe/aphasia/on_lose() - mob_language.remove_language(/datum/language/aphasia) - mob_language.copy_known_languages_from(prev_language) //this will also preserve languages learned during the trauma - QDEL_NULL(prev_language) - mob_language = null + owner.remove_blocked_language(subtypesof(/datum/language/), LANGUAGE_APHASIA) + owner.remove_language(/datum/language/aphasia, TRUE, TRUE, LANGUAGE_APHASIA) ..() /datum/brain_trauma/severe/blindness @@ -271,3 +265,37 @@ ..() if(prob(1) && !owner.has_status_effect(/datum/status_effect/trance)) owner.apply_status_effect(/datum/status_effect/trance, rand(100,300), FALSE) + +/datum/brain_trauma/severe/hypnotic_trigger + name = "Hypnotic Trigger" + desc = "Patient has a trigger phrase set in their subconscious that will trigger a suggestible trance-like state." + scan_desc = "oneiric feedback loop" + gain_text = "You feel odd, like you just forgot something important." + lose_text = "You feel like a weight was lifted from your mind." + random_gain = FALSE + var/trigger_phrase = "Nanotrasen" + +/datum/brain_trauma/severe/hypnotic_trigger/New(phrase) + ..() + if(phrase) + trigger_phrase = phrase + +/datum/brain_trauma/severe/hypnotic_trigger/on_lose() //hypnosis must be cleared separately, but brain surgery should get rid of both anyway + ..() + owner.remove_status_effect(/datum/status_effect/trance) + +/datum/brain_trauma/severe/hypnotic_trigger/handle_hearing(datum/source, list/hearing_args) + if(!owner.can_hear()) + return + if(owner == hearing_args[HEARING_SPEAKER]) + return + + var/regex/reg = new("(\\b[REGEX_QUOTE(trigger_phrase)]\\b)","ig") + + if(findtext(hearing_args[HEARING_RAW_MESSAGE], reg)) + addtimer(CALLBACK(src, .proc/hypnotrigger), 10) //to react AFTER the chat message + hearing_args[HEARING_RAW_MESSAGE] = reg.Replace(hearing_args[HEARING_RAW_MESSAGE], "*********") + +/datum/brain_trauma/severe/hypnotic_trigger/proc/hypnotrigger() + to_chat(owner, "The words trigger something deep within you, and you feel your consciousness slipping away...") + owner.apply_status_effect(/datum/status_effect/trance, rand(100,300), FALSE) diff --git a/code/datums/chatmessage.dm b/code/datums/chatmessage.dm index cbcb34ac5e..7a78e1d001 100644 --- a/code/datums/chatmessage.dm +++ b/code/datums/chatmessage.dm @@ -35,7 +35,7 @@ * * extra_classes - Extra classes to apply to the span that holds the text * * lifespan - The lifespan of the message in deciseconds */ -/datum/chatmessage/New(text, atom/target, mob/owner, list/extra_classes = null, lifespan = CHAT_MESSAGE_LIFESPAN) +/datum/chatmessage/New(text, atom/target, mob/owner, list/extra_classes = list(), lifespan = CHAT_MESSAGE_LIFESPAN) . = ..() if (!istype(target)) CRASH("Invalid target given for chatmessage") @@ -55,6 +55,12 @@ message = null return ..() +/** + * Calls qdel on the chatmessage when its parent is deleted, used to register qdel signal + */ +/datum/chatmessage/proc/on_parent_qdel() + qdel(src) + /** * Generates a chat message image representation * @@ -68,7 +74,7 @@ /datum/chatmessage/proc/generate_image(text, atom/target, mob/owner, list/extra_classes, lifespan) // Register client who owns this message owned_by = owner.client - RegisterSignal(owned_by, COMSIG_PARENT_QDELETING, .proc/qdel, src) + RegisterSignal(owned_by, COMSIG_PARENT_QDELETING, .proc/on_parent_qdel) // Clip message var/maxlen = owned_by.prefs.max_chat_length @@ -108,7 +114,7 @@ // BYOND Bug #2563917 // Construct text var/static/regex/html_metachars = new(@"&[A-Za-z]{1,7};", "g") - var/complete_text = "[text]" + var/complete_text = "[text]" var/mheight = WXH_TO_HEIGHT(owned_by.MeasureText(replacetext(complete_text, html_metachars, "m"), null, CHAT_MESSAGE_WIDTH)) approx_lines = max(1, mheight / CHAT_MESSAGE_APPROX_LHEIGHT) @@ -129,7 +135,7 @@ // Build message image message = image(loc = message_loc, layer = CHAT_LAYER) - message.plane = GAME_PLANE + message.plane = CHAT_PLANE message.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA | KEEP_APART message.alpha = 0 message.pixel_y = owner.bound_height * 0.95 @@ -166,7 +172,7 @@ */ /mob/proc/create_chat_message(atom/movable/speaker, datum/language/message_language, raw_message, list/spans, message_mode) // Ensure the list we are using, if present, is a copy so we don't modify the list provided to us - spans = spans?.Copy() + spans = spans ? spans.Copy() : list() // Check for virtual speakers (aka hearing a message through a radio) var/atom/movable/originalSpeaker = speaker diff --git a/code/datums/components/art.dm b/code/datums/components/art.dm new file mode 100644 index 0000000000..f6d3cb6c61 --- /dev/null +++ b/code/datums/components/art.dm @@ -0,0 +1,56 @@ + +#define BAD_ART 12.5 +#define GOOD_ART 25 +#define GREAT_ART 50 + +/datum/component/art + var/impressiveness = 0 + +/datum/component/art/Initialize(impress) + impressiveness = impress + if(isobj(parent)) + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_obj_examine) + else + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_other_examine) + if(isstructure(parent)) + RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand) + if(isitem(parent)) + RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/apply_moodlet) + +/datum/component/art/proc/apply_moodlet(mob/M, impress) + M.visible_message("[M] stops and looks intently at [parent].", \ + "You stop to take in [parent].") + switch(impress) + if (0 to BAD_ART) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad) + if (BAD_ART to GOOD_ART) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artok", /datum/mood_event/artok) + if (GOOD_ART to GREAT_ART) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgood", /datum/mood_event/artgood) + if(GREAT_ART to INFINITY) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat) + + +/datum/component/art/proc/on_other_examine(datum/source, mob/M) + apply_moodlet(M, impressiveness) + +/datum/component/art/proc/on_obj_examine(datum/source, mob/M) + var/obj/O = parent + apply_moodlet(M, impressiveness *(O.obj_integrity/O.max_integrity)) + +/datum/component/art/proc/on_attack_hand(datum/source, mob/M) + to_chat(M, "You start examining [parent]...") + if(!do_after(M, 20, target = parent)) + return + on_obj_examine(source, M) + +/datum/component/art/rev + +/datum/component/art/rev/apply_moodlet(mob/M, impress) + M.visible_message("[M] stops to inspect [parent].", \ + "You take in [parent], inspecting the fine craftsmanship of the proletariat.") + + if(M.mind && M.mind.has_antag_datum(/datum/antagonist/rev)) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat) + else + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad) diff --git a/code/datums/components/crafting/craft.dm b/code/datums/components/crafting/craft.dm index 8ebd52522a..3283c514b8 100644 --- a/code/datums/components/crafting/craft.dm +++ b/code/datums/components/crafting/craft.dm @@ -209,10 +209,9 @@ var/obj/item/reagent_containers/food/food_result = I var/total_quality = 0 var/total_items = 0 - for(var/obj/item/ingredient in parts) - var/obj/item/reagent_containers/food/food_ingredient = ingredient + for(var/obj/item/reagent_containers/food/ingredient in parts) total_items += 1 - total_quality += food_ingredient.food_quality + total_quality += ingredient.food_quality if(total_items == 0) food_result.adjust_food_quality(50) else diff --git a/code/datums/components/crafting/glassware/glassware.dm b/code/datums/components/crafting/glassware/glassware.dm index 2b57837c5d..6e1a3d47a0 100644 --- a/code/datums/components/crafting/glassware/glassware.dm +++ b/code/datums/components/crafting/glassware/glassware.dm @@ -74,7 +74,7 @@ //////////////////////Lens////////////////////////// //Six Steps // -//Sells for 1800 cr, takes 15 glass shets // +//Sells for 1600 cr, takes 15 glass shets // //Usefull for selling and later crafting // //////////////////////////////////////////////////// @@ -146,14 +146,14 @@ /obj/item/glasswork/glass_base/glass_lens_part5 name = "Unpolished glass lens" - desc = "A small unpolished glass lens. Could be polished with some silk." + desc = "A small unpolished glass lens. Could be polished with some cloth." icon = 'icons/obj/glass_ware.dmi' icon_state = "glass_optics" next_step = /obj/item/glasswork/glass_base/glass_lens_part6 /obj/item/glasswork/glass_base/glass_lens_part5/attackby(obj/item/I, mob/user, params) ..() - if(istype(I, /obj/item/stack/sheet/silk)) + if(istype(I, /obj/item/stack/sheet/cloth)) if(do_after(user,10, target = src)) new next_step(user.loc, 1) qdel(src) @@ -324,7 +324,7 @@ //////////////////////Tea Plates//////////////////// //Three Steps // -//Sells for 1200 cr, takes 5 glass shets // +//Sells for 1000 cr, takes 5 glass shets // //Usefull for selling and chemical things // //////////////////////////////////////////////////// @@ -370,20 +370,20 @@ /obj/item/glasswork/glass_base/tea_plate3 name = "Disk of glass" - desc = "A disk of glass that can be cant be used for much. Needs to be polished with some silk." + desc = "A disk of glass that can be cant be used for much. Needs to be polished with some cloth." icon_state = "glass_base_half" next_step = /obj/item/tea_plate /obj/item/glasswork/glass_base/tea_plate3/attackby(obj/item/I, mob/user, params) ..() - if(istype(I, /obj/item/stack/sheet/silk)) + if(istype(I, /obj/item/stack/sheet/cloth)) if(do_after(user,10, target = src)) new next_step(user.loc, 1) qdel(src) //////////////////////Tea Cup/////////////////////// //Four Steps // -//Sells for 1800 cr, takes 6 glass shets // +//Sells for 1600 cr, takes 6 glass shets // //Usefull for selling and chemical things // //////////////////////////////////////////////////// @@ -429,13 +429,13 @@ /obj/item/glasswork/glass_base/tea_cup3 name = "Disk of glass" - desc = "A bowl of glass that can be cant be used for much. Needs to be polished with some silk." + desc = "A bowl of glass that can be cant be used for much. Needs to be polished with some cloth." icon_state = "glass_base_half" next_step = /obj/item/glasswork/glass_base/tea_cup4 /obj/item/glasswork/glass_base/cup3/attackby(obj/item/I, mob/user, params) ..() - if(istype(I, /obj/item/stack/sheet/silk)) + if(istype(I, /obj/item/stack/sheet/cloth)) if(do_after(user,10, target = src)) new next_step(user.loc, 1) qdel(src) diff --git a/code/datums/components/crafting/guncrafting.dm b/code/datums/components/crafting/guncrafting.dm index 89868c2332..e06583ab61 100644 --- a/code/datums/components/crafting/guncrafting.dm +++ b/code/datums/components/crafting/guncrafting.dm @@ -1,21 +1,20 @@ //Gun crafting parts til they can be moved elsewhere // PARTS // +/obj/item/weaponcrafting + icon = 'icons/obj/improvised.dmi' /obj/item/weaponcrafting/receiver name = "modular receiver" desc = "A prototype modular receiver and trigger assembly for a firearm." - icon = 'icons/obj/improvised.dmi' icon_state = "receiver" /obj/item/weaponcrafting/stock name = "rifle stock" desc = "A classic rifle stock that doubles as a grip, roughly carved out of wood." - icon = 'icons/obj/improvised.dmi' icon_state = "riflestock" -/obj/item/weaponcrafting/silkstring - name = "silkstring" - desc = "A long piece of silk with some resemblance to cable coil." - icon = 'icons/obj/improvised.dmi' - icon_state = "silkstring" +/obj/item/weaponcrafting/durathread_string + name = "durathread string" + desc = "A long piece of durathread with some resemblance to cable coil." + icon_state = "durastring" diff --git a/code/datums/components/crafting/recipes/recipes_clothing.dm b/code/datums/components/crafting/recipes/recipes_clothing.dm index 02dd3f2c05..7a7379c834 100644 --- a/code/datums/components/crafting/recipes/recipes_clothing.dm +++ b/code/datums/components/crafting/recipes/recipes_clothing.dm @@ -39,14 +39,14 @@ time = 10 reqs = list(/obj/item/paper = 20) category = CAT_CLOTHING - + /datum/crafting_recipe/armwraps name = "Armwraps" result = /obj/item/clothing/gloves/fingerless/pugilist time = 60 tools = list(TOOL_WIRECUTTER) reqs = list(/obj/item/stack/sheet/cloth = 4, - /obj/item/stack/sheet/silk = 2, + /obj/item/stack/sheet/durathread = 2, /obj/item/stack/sheet/leather = 2) category = CAT_CLOTHING diff --git a/code/datums/components/crafting/recipes/recipes_misc.dm b/code/datums/components/crafting/recipes/recipes_misc.dm index 49d7a8dfea..1ad53aae67 100644 --- a/code/datums/components/crafting/recipes/recipes_misc.dm +++ b/code/datums/components/crafting/recipes/recipes_misc.dm @@ -117,7 +117,7 @@ /datum/crafting_recipe/upgraded_gauze name = "Improved Gauze" - result = /obj/item/stack/medical/gauze/adv + result = /obj/item/stack/medical/gauze/adv/one time = 1 reqs = list(/obj/item/stack/medical/gauze = 1, /datum/reagent/space_cleaner/sterilizine = 10) @@ -126,7 +126,7 @@ /datum/crafting_recipe/bruise_pack name = "Bruise Pack" - result = /obj/item/stack/medical/bruise_pack + result = /obj/item/stack/medical/bruise_pack/one time = 1 reqs = list(/obj/item/stack/medical/gauze = 1, /datum/reagent/medicine/styptic_powder = 10) @@ -134,8 +134,8 @@ subcategory = CAT_TOOL /datum/crafting_recipe/burn_pack - name = "Brun Ointment" - result = /obj/item/stack/medical/ointment + name = "Burn Ointment" + result = /obj/item/stack/medical/ointment/one time = 1 reqs = list(/obj/item/stack/medical/gauze = 1, /datum/reagent/medicine/silver_sulfadiazine = 10) @@ -157,7 +157,7 @@ /datum/crafting_recipe/goldenbox name = "Gold Plated Toolbox" result = /obj/item/storage/toolbox/gold_fake - tools = list(/obj/item/stock_parts/cell/upgraded/plus) + tools = list(/obj/item/stock_parts/cell/high) reqs = list(/obj/item/stack/sheet/cardboard = 1, //so we dont null items in crafting /obj/item/stack/cable_coil = 10, /obj/item/stack/sheet/mineral/gold = 1, @@ -184,7 +184,7 @@ /datum/crafting_recipe/bronze_driver name = "Bronze Plated Screwdriver" - tools = list(/obj/item/stock_parts/cell/upgraded/plus) + tools = list(/obj/item/stock_parts/cell/high) result = /obj/item/screwdriver/bronze reqs = list(/obj/item/screwdriver = 1, /obj/item/stack/cable_coil = 10, @@ -196,7 +196,7 @@ /datum/crafting_recipe/bronze_welder name = "Bronze Plated Welding Tool" - tools = list(/obj/item/stock_parts/cell/upgraded/plus) + tools = list(/obj/item/stock_parts/cell/high) result = /obj/item/weldingtool/bronze reqs = list(/obj/item/weldingtool = 1, /obj/item/stack/cable_coil = 10, @@ -208,7 +208,7 @@ /datum/crafting_recipe/bronze_wirecutters name = "Bronze Plated Wirecutters" - tools = list(/obj/item/stock_parts/cell/upgraded/plus) + tools = list(/obj/item/stock_parts/cell/high) result = /obj/item/wirecutters/bronze reqs = list(/obj/item/wirecutters = 1, /obj/item/stack/cable_coil = 10, @@ -220,7 +220,7 @@ /datum/crafting_recipe/bronze_crowbar name = "Bronze Plated Crowbar" - tools = list(/obj/item/stock_parts/cell/upgraded/plus) + tools = list(/obj/item/stock_parts/cell/high) result = /obj/item/crowbar/bronze reqs = list(/obj/item/crowbar = 1, /obj/item/stack/cable_coil = 10, @@ -232,7 +232,7 @@ /datum/crafting_recipe/bronze_wrench name = "Bronze Plated Wrench" - tools = list(/obj/item/stock_parts/cell/upgraded/plus) + tools = list(/obj/item/stock_parts/cell/high) result = /obj/item/wrench/bronze reqs = list(/obj/item/wrench = 1, /obj/item/stack/cable_coil = 10, diff --git a/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm b/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm index b037f02f80..21a160264a 100644 --- a/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm +++ b/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm @@ -192,7 +192,7 @@ result = /obj/item/gun/ballistic/bow/pipe reqs = list(/obj/item/pipe = 5, /obj/item/stack/sheet/plastic = 15, - /obj/item/weaponcrafting/silkstring = 5) + /obj/item/weaponcrafting/durathread_string = 5) time = 450 category = CAT_WEAPONRY subcategory = CAT_WEAPON @@ -281,7 +281,7 @@ result = /obj/item/ammo_casing/caseless/arrow/wood time = 30 reqs = list(/obj/item/stack/sheet/mineral/wood = 1, - /obj/item/stack/sheet/silk = 1, + /obj/item/stack/sheet/durathread = 1, /obj/item/stack/rods = 1) // 1 metal sheet = 2 rods = 2 arrows category = CAT_WEAPONRY subcategory = CAT_AMMO diff --git a/code/datums/components/empprotection.dm b/code/datums/components/empprotection.dm deleted file mode 100644 index c85cdf31c7..0000000000 --- a/code/datums/components/empprotection.dm +++ /dev/null @@ -1,11 +0,0 @@ -/datum/component/empprotection - var/flags = NONE - -/datum/component/empprotection/Initialize(_flags) - if(!istype(parent, /atom)) - return COMPONENT_INCOMPATIBLE - flags = _flags - RegisterSignal(parent, list(COMSIG_ATOM_EMP_ACT), .proc/getEmpFlags) - -/datum/component/empprotection/proc/getEmpFlags(datum/source, severity) - return flags diff --git a/code/datums/components/fantasy/_fantasy.dm b/code/datums/components/fantasy/_fantasy.dm index a203264fae..8441f962f9 100644 --- a/code/datums/components/fantasy/_fantasy.dm +++ b/code/datums/components/fantasy/_fantasy.dm @@ -9,6 +9,7 @@ var/originalName var/list/affixes var/list/appliedComponents + var/list/appliedElements var/static/list/affixListing @@ -22,6 +23,7 @@ src.affixes = affixes appliedComponents = list() + appliedElements = list() randomAffixes() /datum/component/fantasy/Destroy() @@ -118,6 +120,8 @@ affix.remove(src) for(var/i in appliedComponents) qdel(i) + for(var/i in appliedElements) + master._RemoveElement(i) master.force = max(0, master.force - quality) master.throwforce = max(0, master.throwforce - quality) diff --git a/code/datums/components/fantasy/prefixes.dm b/code/datums/components/fantasy/prefixes.dm index 5ef2ac2baf..b6de85cab0 100644 --- a/code/datums/components/fantasy/prefixes.dm +++ b/code/datums/components/fantasy/prefixes.dm @@ -45,7 +45,8 @@ /datum/fantasy_affix/tactical/apply(datum/component/fantasy/comp, newName) var/obj/item/master = comp.parent - comp.appliedComponents += master.AddComponent(/datum/component/tactical) + master.AddElement(/datum/element/tactical) + comp.appliedElements += list(/datum/element/tactical) return "tactical [newName]" /datum/fantasy_affix/pyromantic diff --git a/code/datums/components/field_of_vision.dm b/code/datums/components/field_of_vision.dm new file mode 100644 index 0000000000..5fb7b2596c --- /dev/null +++ b/code/datums/components/field_of_vision.dm @@ -0,0 +1,354 @@ +#define CENTERED_RENDER_SOURCE(img, atom, FoV) \ + atom.render_target = atom.render_target || ref(atom);\ + img.render_source = atom.render_target;\ + if(atom.icon){\ + var/_cached_sizes = FoV.width_n_height_offsets[atom.icon];\ + if(!_cached_sizes){\ + var/icon/_I = icon(atom.icon);\ + var/list/L = list();\ + L += (_I.Width() - world.icon_size)/2;\ + L += (_I.Height() - world.icon_size)/2;\ + _cached_sizes = FoV.width_n_height_offsets[atom.icon] = L\ + }\ + img.pixel_x = _cached_sizes[1];\ + img.pixel_y = _cached_sizes[2];\ + img.loc = atom\ + } + +#define REGISTER_NESTED_LOCS(source, list, comsig, proc) \ + for(var/k in get_nested_locs(source)){\ + var/atom/_A = k;\ + RegisterSignal(_A, comsig, proc);\ + list += _A\ + } + +#define UNREGISTER_NESTED_LOCS(list, comsig, index) \ + for(var/k in index to length(list)){\ + var/atom/_A = list[k];\ + UnregisterSignal(_A, comsig);\ + list -= _A\ + } + +/** + * Field of Vision component. Does totally what you probably think it does, + * ergo preventing players from seeing what's behind them. + */ +/datum/component/field_of_vision + can_transfer = TRUE + +/** + * That special invisible, almost neigh indestructible movable + * that holds both shadow cone mask and image and follows the player around. + */ + var/atom/movable/fov_holder/fov + ///The current screen size this field of vision is meant to fit for. + var/current_fov_size = list(15, 15) + ///How much is the cone rotated clockwise, purely backend. Please use rotate_shadow_cone() if you must. + var/angle = 0 + /// Used to scale the shadow cone when rotating it to fit over the edges of the screen. + var/rot_scale = 1 + /// The inner angle of this cone, right hardset to 90, 180, or 270 degrees, until someone figures out a way to make it dynamic. + var/shadow_angle = FOV_90_DEGREES + /// The mask portion of the cone, placed on a * render target plane so while not visible it still applies the filter. + var/image/shadow_mask + /// The visual portion of the cone, placed on the highest layer of the wall plane + var/image/visual_shadow +/** + * An image whose render_source is kept up to date to prevent the mob (or the topmost movable holding it) from being hidden by the mask. + * Will make it use vis_contents instead once a few byonds bugs with images and vis contents are fixed. + */ + var/image/owner_mask +/** + * A circle image used to somewhat uncover the adjacent portion of the shadow cone, making mobs and objects behind us somewhat visible. + * The owner mask is still required for those mob going over the default 32x32 px size btw. + */ + var/image/adj_mask + /// A list of nested locations the mob is in, to ensure the above image works correctly. + var/list/nested_locs = list() +/** + * A static list of offsets based on icon width and height, because render sources are centered unlike most other visuals, + * and that gives us some problems when the icon is larger or smaller than world.icon_size + */ + var/static/list/width_n_height_offsets = list() + +/datum/component/field_of_vision/Initialize(fov_type = FOV_90_DEGREES, _angle = 0) + if(!ismob(parent)) + return COMPONENT_INCOMPATIBLE + angle = _angle + shadow_angle = fov_type + +/datum/component/field_of_vision/RegisterWithParent() + . = ..() + var/mob/M = parent + if(M.client) + generate_fov_holder(M, angle) + RegisterSignal(M, COMSIG_MOB_CLIENT_LOGIN, .proc/on_mob_login) + RegisterSignal(M, COMSIG_MOB_CLIENT_LOGOUT, .proc/on_mob_logout) + RegisterSignal(M, COMSIG_MOB_GET_VISIBLE_MESSAGE, .proc/on_visible_message) + RegisterSignal(M, COMSIG_MOB_EXAMINATE, .proc/on_examinate) + RegisterSignal(M, COMSIG_MOB_FOV_VIEW, .proc/on_fov_view) + RegisterSignal(M, COMSIG_MOB_CLIENT_CHANGE_VIEW, .proc/on_change_view) + RegisterSignal(M, COMSIG_MOB_RESET_PERSPECTIVE, .proc/on_reset_perspective) + RegisterSignal(M, COMSIG_MOB_FOV_VIEWER, .proc/is_viewer) + +/datum/component/field_of_vision/UnregisterFromParent() + . = ..() + var/mob/M = parent + if(!QDELETED(fov)) + if(M.client) + UnregisterSignal(M, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_MOVABLE_MOVED, COMSIG_MOB_DEATH, COMSIG_LIVING_REVIVE)) + M.client.images -= owner_mask + M.client.images -= shadow_mask + M.client.images -= visual_shadow + M.client.images -= adj_mask + qdel(fov, TRUE) // Forced. + fov = null + QDEL_NULL(owner_mask) + QDEL_NULL(adj_mask) + if(length(nested_locs)) + UNREGISTER_NESTED_LOCS(nested_locs, COMSIG_MOVABLE_MOVED, 1) + UnregisterSignal(M, list(COMSIG_MOB_CLIENT_LOGIN, COMSIG_MOB_CLIENT_LOGOUT, + COMSIG_MOB_GET_VISIBLE_MESSAGE, COMSIG_MOB_EXAMINATE, + COMSIG_MOB_FOV_VIEW, COMSIG_MOB_RESET_PERSPECTIVE, + COMSIG_MOB_CLIENT_CHANGE_VIEW, COMSIG_MOB_FOV_VIEWER)) + +/** + * Generates the holder and images (if not generated yet) and adds them to client.images. + * Run when the component is registered to a player mob, or upon login. + */ +/datum/component/field_of_vision/proc/generate_fov_holder(mob/M, _angle = 0) + if(QDELETED(fov)) + fov = new(get_turf(M)) + fov.icon_state = "[shadow_angle]" + fov.dir = M.dir + shadow_mask = image('icons/misc/field_of_vision.dmi', fov, "[shadow_angle]", FIELD_OF_VISION_LAYER) + shadow_mask.plane = FIELD_OF_VISION_PLANE + visual_shadow = image('icons/misc/field_of_vision.dmi', fov, "[shadow_angle]_v", FIELD_OF_VISION_LAYER) + visual_shadow.plane = FIELD_OF_VISION_VISUAL_PLANE + owner_mask = new + owner_mask.appearance_flags = RESET_TRANSFORM + owner_mask.plane = FIELD_OF_VISION_BLOCKER_PLANE + adj_mask = image('icons/misc/field_of_vision.dmi', fov, "adj_mask", FIELD_OF_VISION_LAYER) + adj_mask.appearance_flags = RESET_TRANSFORM + adj_mask.plane = FIELD_OF_VISION_BLOCKER_PLANE + if(_angle) + rotate_shadow_cone(_angle) + fov.alpha = M.stat == DEAD ? 0 : 255 + RegisterSignal(M, COMSIG_MOB_DEATH, .proc/hide_fov) + RegisterSignal(M, COMSIG_LIVING_REVIVE, .proc/show_fov) + RegisterSignal(M, COMSIG_ATOM_DIR_CHANGE, .proc/on_dir_change) + RegisterSignal(M, COMSIG_MOVABLE_MOVED, .proc/on_mob_moved) + RegisterSignal(M, COMSIG_ROBOT_UPDATE_ICONS, .proc/manual_centered_render_source) + var/atom/A = M + if(M.loc && !isturf(M.loc)) + REGISTER_NESTED_LOCS(M, nested_locs, COMSIG_MOVABLE_MOVED, .proc/on_loc_moved) + A = nested_locs[nested_locs.len] + CENTERED_RENDER_SOURCE(owner_mask, A, src) + M.client.images += shadow_mask + M.client.images += visual_shadow + M.client.images += owner_mask + M.client.images += adj_mask + if(M.client.view != "[current_fov_size[1]]x[current_fov_size[2]]") + resize_fov(current_fov_size, getviewsize(M.client.view)) + +///Rotates the shadow cone to a certain degree. Backend shenanigans. +/datum/component/field_of_vision/proc/rotate_shadow_cone(new_angle) + var/simple_degrees = SIMPLIFY_DEGREES(new_angle - angle) + var/to_scale = cos(simple_degrees) * sin(simple_degrees) + if(to_scale) + var/old_rot_scale = rot_scale + rot_scale = 1 + to_scale + if(old_rot_scale != rot_scale) + visual_shadow.transform = shadow_mask.transform = shadow_mask.transform.Scale(rot_scale/old_rot_scale) + visual_shadow.transform = shadow_mask.transform = shadow_mask.transform.Turn(fov.transform, simple_degrees) + +/** + * Resizes the shadow to match the current screen size. + * Run when the client view size is changed, or if the player has a viewsize different than "15x15" on login/comp registration. + */ +/datum/component/field_of_vision/proc/resize_fov(list/old_view, list/view) + current_fov_size = view + var/old_size = max(old_view[1], old_view[2]) + var/new_size = max(view[1], view[2]) + if(old_size == new_size) //longest edges are still of the same length. + return + visual_shadow.transform = shadow_mask.transform = shadow_mask.transform.Scale(new_size/old_size) + +/datum/component/field_of_vision/proc/on_mob_login(mob/source, client/client) + generate_fov_holder(source, angle) + +/datum/component/field_of_vision/proc/on_mob_logout(mob/source, client/client) + UnregisterSignal(source, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_MOVABLE_MOVED, COMSIG_MOB_DEATH, + COMSIG_LIVING_REVIVE, COMSIG_ROBOT_UPDATE_ICONS)) + if(length(nested_locs)) + UNREGISTER_NESTED_LOCS(nested_locs, COMSIG_MOVABLE_MOVED, 1) + +/datum/component/field_of_vision/proc/on_dir_change(mob/source, old_dir, new_dir) + fov.dir = new_dir + +///Hides the shadow, other visibility comsig procs will take it into account. Called when the mob dies. +/datum/component/field_of_vision/proc/hide_fov(mob/source) + fov.alpha = 0 + +/// Shows the shadow. Called when the mob is revived. +/datum/component/field_of_vision/proc/show_fov(mob/source) + fov.alpha = 255 + +/// Hides the shadow when looking through other items, shows it otherwise. +/datum/component/field_of_vision/proc/on_reset_perspective(mob/source, atom/target) + if(source.client.eye == source || source.client.eye == source.loc) + fov.alpha = 255 + else + fov.alpha = 0 + +/// Called when the client view size is changed. +/datum/component/field_of_vision/proc/on_change_view(mob/source, client, list/old_view, list/view) + resize_fov(old_view, view) + +/** + * Called when the owner mob moves around. Used to keep shadow located right behind us, + * As well as modify the owner mask to match the topmost item. + */ +/datum/component/field_of_vision/proc/on_mob_moved(mob/source, atom/oldloc, dir, forced) + var/turf/T + if(!isturf(source.loc)) //Recalculate all nested locations. + UNREGISTER_NESTED_LOCS( nested_locs, COMSIG_MOVABLE_MOVED, 1) + REGISTER_NESTED_LOCS(source, nested_locs, COMSIG_MOVABLE_MOVED, .proc/on_loc_moved) + var/atom/movable/topmost = nested_locs[nested_locs.len] + T = topmost.loc + CENTERED_RENDER_SOURCE(owner_mask, topmost, src) + else + T = source.loc + if(length(nested_locs)) + UNREGISTER_NESTED_LOCS(nested_locs, COMSIG_MOVABLE_MOVED, 1) + CENTERED_RENDER_SOURCE(owner_mask, source, src) + if(T) + fov.forceMove(T, harderforce = TRUE) + +/// Pretty much like the above, but meant for other movables the mob is stored in (bodybags, boxes, mechs etc). +/datum/component/field_of_vision/proc/on_loc_moved(atom/movable/source, atom/oldloc, dir, forced) + if(isturf(source.loc) && isturf(oldloc)) //This is the case of the topmost movable loc moving around the world, skip. + fov.forceMove(source.loc, harderforce = TRUE) + return + var/atom/movable/prev_topmost = nested_locs[nested_locs.len] + if(prev_topmost != source) + UNREGISTER_NESTED_LOCS(nested_locs, COMSIG_MOVABLE_MOVED, nested_locs.Find(source) + 1) + REGISTER_NESTED_LOCS(source, nested_locs, COMSIG_MOVABLE_MOVED, .proc/on_loc_moved) + var/atom/movable/topmost = nested_locs[nested_locs.len] + if(topmost != prev_topmost) + CENTERED_RENDER_SOURCE(owner_mask, topmost, src) + if(topmost.loc) + fov.forceMove(topmost.loc, harderforce = TRUE) + +/// A hacky comsig proc for things that somehow decide to change icon on the go. may make a change_icon_file() proc later but... +/datum/component/field_of_vision/proc/manual_centered_render_source(mob/source, old_icon) + if(!isturf(source.loc)) + return + CENTERED_RENDER_SOURCE(owner_mask, source, src) + +#undef CENTERED_RENDER_SOURCE +#undef REGISTER_NESTED_LOCS +#undef UNREGISTER_NESTED_LOCS + +/** + * Byond doc is not entirely correct on the integrated arctan() proc. + * When both x and y are negative, the output is also negative, cycling clockwise instead of counter-clockwise. + * That's also why I am extensively using the SIMPLIFY_DEGREES macro here. + * + * Overall this is the main macro that calculates wheter a target is within the shadow cone angle or not. + */ +#define FOV_ANGLE_CHECK(mob, target, zero_x_y_statement, success_statement) \ + var/turf/T1 = get_turf(target);\ + var/turf/T2 = get_turf(mob);\ + if(!T1 || !T2){\ + zero_x_y_statement\ + }\ + var/_x = (T1.x - T2.x);\ + var/_y = (T1.y - T2.y);\ + if(ISINRANGE(_x, -1, 1) && ISINRANGE(_y, -1, 1)){\ + zero_x_y_statement\ + }\ + var/dir = (mob.dir & (EAST|WEST)) || mob.dir;\ + var/_degree = -angle;\ + var/_half = shadow_angle/2;\ + switch(dir){\ + if(EAST){\ + _degree += 180;\ + }\ + if(NORTH){\ + _degree += 270;\ + }\ + if(SOUTH){\ + _degree += 90;\ + }\ + }\ + var/_min = SIMPLIFY_DEGREES(_degree - _half);\ + var/_max = SIMPLIFY_DEGREES(_degree + _half);\ + if((_min > _max) ? !ISINRANGE(SIMPLIFY_DEGREES(arctan(_x, _y)), _max, _min) : ISINRANGE(SIMPLIFY_DEGREES(arctan(_x, _y)), _min, _max)){\ + success_statement;\ + } + +/datum/component/field_of_vision/proc/on_examinate(mob/source, atom/target) + if(fov.alpha) + FOV_ANGLE_CHECK(source, target, return, return COMPONENT_DENY_EXAMINATE|COMPONENT_EXAMINATE_BLIND) + +/datum/component/field_of_vision/proc/on_visible_message(mob/source, atom/target, message, range, list/ignored_mobs) + if(fov.alpha) + FOV_ANGLE_CHECK(source, target, return, return COMPONENT_NO_VISIBLE_MESSAGE) + +/datum/component/field_of_vision/proc/on_fov_view(mob/source, list/atoms) + if(!fov.alpha) + return + for(var/k in atoms) + var/atom/A = k + FOV_ANGLE_CHECK(source, A, continue, atoms -= A) + +/datum/component/field_of_vision/proc/is_viewer(mob/source, atom/center, depth, list/viewers_list) + if(fov.alpha) + FOV_ANGLE_CHECK(source, center, return, viewers_list -= source) + +#undef FOV_ANGLE_CHECK + +/** + * The shadow cone's mask and visual images holder which can't locate inside the mob, + * lest they inherit the mob opacity and cause a lot of hindrance + */ +/atom/movable/fov_holder + name = "field of vision holder" + pixel_x = -224 //the image is about 480x480 px, ergo 15 tiles (480/32) big, and we gotta center it. + pixel_y = -224 + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + plane = FIELD_OF_VISION_PLANE + anchored = TRUE + +/atom/movable/fov_holder/ConveyorMove() + return + +/atom/movable/fov_holder/has_gravity(turf/T) + return FALSE + +/atom/movable/fov_holder/ex_act(severity) + return FALSE + +/atom/movable/fov_holder/singularity_act() + return + +/atom/movable/fov_holder/singularity_pull() + return + +/atom/movable/fov_holder/blob_act() + return + +/atom/movable/fov_holder/onTransitZ() + return + +/// Prevents people from moving these after creation, because they shouldn't be. +/atom/movable/fov_holder/forceMove(atom/destination, no_tp=FALSE, harderforce = FALSE) + if(harderforce) + return ..() + +/// Last but not least, these shouldn't be deleted by anything but the component itself +/atom/movable/fov_holder/Destroy(force = FALSE) + if(!force) + return QDEL_HINT_LETMELIVE + return ..() diff --git a/code/datums/components/footstep.dm b/code/datums/components/footstep.dm index fbf559fe35..f767c607a5 100644 --- a/code/datums/components/footstep.dm +++ b/code/datums/components/footstep.dm @@ -1,26 +1,52 @@ +///Footstep component. Plays footsteps at parents location when it is appropriate. /datum/component/footstep + ///How many steps the parent has taken since the last time a footstep was played var/steps = 0 + ///volume determines the extra volume of the footstep. This is multiplied by the base volume, should there be one. var/volume + ///e_range stands for extra range - aka how far the sound can be heard. This is added to the base value and ignored if there isn't a base value. var/e_range + ///footstep_type is a define which determines what kind of sounds should get chosen. + var/footstep_type + ///This can be a list OR a soundfile OR null. Determines whatever sound gets played. + var/footstep_sounds -/datum/component/footstep/Initialize(volume_ = 0.5, e_range_ = -1) +/datum/component/footstep/Initialize(footstep_type_ = FOOTSTEP_MOB_BAREFOOT, volume_ = 0.5, e_range_ = -1) if(!isliving(parent)) return COMPONENT_INCOMPATIBLE volume = volume_ e_range = e_range_ - RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/play_footstep) + footstep_type = footstep_type_ + switch(footstep_type) + if(FOOTSTEP_MOB_HUMAN) + if(!ishuman(parent)) + return COMPONENT_INCOMPATIBLE + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/play_humanstep) + return + if(FOOTSTEP_MOB_CLAW) + footstep_sounds = GLOB.clawfootstep + if(FOOTSTEP_MOB_BAREFOOT) + footstep_sounds = GLOB.barefootstep + if(FOOTSTEP_MOB_HEAVY) + footstep_sounds = GLOB.heavyfootstep + if(FOOTSTEP_MOB_SHOE) + footstep_sounds = GLOB.footstep + if(FOOTSTEP_MOB_SLIME) + footstep_sounds = 'sound/effects/footstep/slime1.ogg' + if(FOOTSTEP_MOB_CRAWL) + footstep_sounds = 'sound/effects/footstep/crawl1.ogg' + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/play_simplestep) //Note that this doesn't get called for humans. -/datum/component/footstep/proc/play_footstep() +///Prepares a footstep. Determines if it should get played. Returns the turf it should get played on. Note that it is always a /turf/open +/datum/component/footstep/proc/prepare_step() var/turf/open/T = get_turf(parent) if(!istype(T)) return var/mob/living/LM = parent - var/v = volume - var/e = e_range if(!T.footstep || LM.buckled || !CHECK_MOBILITY(LM, MOBILITY_STAND) || LM.buckled || LM.throwing || (LM.movement_type & (VENTCRAWLING | FLYING))) if (LM.lying && !LM.buckled && !(!T.footstep || LM.movement_type & (VENTCRAWLING | FLYING))) //play crawling sound if we're lying - playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * v) + playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * volume) return if(HAS_TRAIT(LM, TRAIT_SILENT_STEP)) @@ -30,79 +56,83 @@ var/mob/living/carbon/C = LM if(!C.get_bodypart(BODY_ZONE_L_LEG) && !C.get_bodypart(BODY_ZONE_R_LEG)) return - if(ishuman(C) && C.m_intent == MOVE_INTENT_WALK) - v /= 2 - e -= 5 + if(C.m_intent == MOVE_INTENT_WALK) + return steps++ - if(steps >= 3) + if(steps >= 6) steps = 0 - else + if(steps % 2) return - if(prob(80) && !LM.has_gravity(T)) // don't need to step as often when you hop around + if(steps != 0 && !LM.has_gravity(T)) // don't need to step as often when you hop around return + return T - //begin playsound shenanigans// - - //for barefooted non-clawed mobs like monkeys - if(isbarefoot(LM)) - playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]), - GLOB.barefootstep[T.barefootstep][2] * v, - TRUE, - GLOB.barefootstep[T.barefootstep][3] + e) +/datum/component/footstep/proc/play_simplestep() + var/turf/open/T = prepare_step() + if(!T) return - - //for xenomorphs, dogs, and other clawed mobs - if(isclawfoot(LM)) - if(isalienadult(LM)) //xenos are stealthy and get quieter footsteps - v /= 3 - e -= 5 - - playsound(T, pick(GLOB.clawfootstep[T.clawfootstep][1]), - GLOB.clawfootstep[T.clawfootstep][2] * v, - TRUE, - GLOB.clawfootstep[T.clawfootstep][3] + e) + if(isfile(footstep_sounds) || istext(footstep_sounds)) + playsound(T, footstep_sounds, volume) return - - //for megafauna and other large and imtimidating mobs such as the bloodminer - if(isheavyfoot(LM)) - playsound(T, pick(GLOB.heavyfootstep[T.heavyfootstep][1]), - GLOB.heavyfootstep[T.heavyfootstep][2] * v, - TRUE, - GLOB.heavyfootstep[T.heavyfootstep][3] + e) + var/turf_footstep + switch(footstep_type) + if(FOOTSTEP_MOB_CLAW) + turf_footstep = T.clawfootstep + if(FOOTSTEP_MOB_BAREFOOT) + turf_footstep = T.barefootstep + if(FOOTSTEP_MOB_HEAVY) + turf_footstep = T.heavyfootstep + if(FOOTSTEP_MOB_SHOE) + turf_footstep = T.footstep + if(!turf_footstep) return + playsound(T, pick(footstep_sounds[turf_footstep][1]), footstep_sounds[turf_footstep][2] * volume, TRUE, footstep_sounds[turf_footstep][3] + e_range) - //for slimes - if(isslime(LM)) - playsound(T, 'sound/effects/footstep/slime1.ogg', 15 * v) +/datum/component/footstep/proc/play_humanstep() + var/turf/open/T = prepare_step() + if(!T) return - - //for (simple) humanoid mobs (clowns, russians, pirates, etc.) - if(isshoefoot(LM)) - if(!ishuman(LM)) - playsound(T, pick(GLOB.footstep[T.footstep][1]), - GLOB.footstep[T.footstep][2] * v, - TRUE, - GLOB.footstep[T.footstep][3] + e) - return - if(ishuman(LM)) //for proper humans, they're special - var/mob/living/carbon/human/H = LM - var/feetCover = (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)) || (H.w_uniform && (H.w_uniform.body_parts_covered & FEET) || (H.shoes && (H.shoes.body_parts_covered & FEET))) - - if (H.dna.features["taur"] == "Naga" || H.dna.features["taur"] == "Tentacle") //are we a naga or tentacle taur creature - playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * v) + var/mob/living/carbon/human/H = parent + var/list/L = GLOB.barefootstep + var/turf_footstep = T.barefootstep + var/special = FALSE + if(H.physiology.footstep_type) + switch(H.physiology.footstep_type) + if(FOOTSTEP_MOB_CLAW) + turf_footstep = T.clawfootstep + L = GLOB.clawfootstep + if(FOOTSTEP_MOB_BAREFOOT) + turf_footstep = T.barefootstep + L = GLOB.barefootstep + if(FOOTSTEP_MOB_HEAVY) + turf_footstep = T.heavyfootstep + L = GLOB.heavyfootstep + if(FOOTSTEP_MOB_SHOE) + turf_footstep = T.footstep + L = GLOB.footstep + if(FOOTSTEP_MOB_SLIME) + playsound(T, 'sound/effects/footstep/slime1.ogg', 50 * volume) return + if(FOOTSTEP_MOB_CRAWL) + playsound(T, 'sound/effects/footstep/crawl1.ogg', 50 * volume) + return + special = TRUE + else + var/feetCover = (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)) || (H.w_uniform && (H.w_uniform.body_parts_covered & FEET) || (H.shoes && (H.shoes.body_parts_covered & FEET))) + if(feetCover) //are we wearing shoes + playsound(T, pick(GLOB.footstep[T.footstep][1]), + GLOB.footstep[T.footstep][2] * volume, + TRUE, + GLOB.footstep[T.footstep][3] + e_range) + return - if(feetCover) //are we wearing shoes - playsound(T, pick(GLOB.footstep[T.footstep][1]), - GLOB.footstep[T.footstep][2] * v, - TRUE, - GLOB.footstep[T.footstep][3] + e) - - if(!feetCover) //are we NOT wearing shoes - playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]), - GLOB.barefootstep[T.barefootstep][2] * v, - TRUE, - GLOB.barefootstep[T.barefootstep][3] + e) \ No newline at end of file + if(!special && H.dna.species.special_step_sounds) + playsound(T, pick(H.dna.species.special_step_sounds), 50, TRUE) + else + playsound(T, pick(L[turf_footstep][1]), + L[turf_footstep][2] * volume, + TRUE, + L[turf_footstep][3] + e_range) diff --git a/code/datums/components/forced_gravity.dm b/code/datums/components/forced_gravity.dm deleted file mode 100644 index 100bcf781c..0000000000 --- a/code/datums/components/forced_gravity.dm +++ /dev/null @@ -1,20 +0,0 @@ -/datum/component/forced_gravity - var/gravity - var/ignore_space = FALSE //If forced gravity should also work on space turfs - -/datum/component/forced_gravity/Initialize(forced_value = 1) - if(!isatom(parent)) - return COMPONENT_INCOMPATIBLE - RegisterSignal(COMSIG_ATOM_HAS_GRAVITY, .proc/gravity_check) - if(isturf(parent)) - RegisterSignal(COMSIG_TURF_HAS_GRAVITY, .proc/turf_gravity_check) - - gravity = forced_value - -/datum/component/forced_gravity/proc/gravity_check(datum/source, turf/location, list/gravs) - if(!ignore_space && isspaceturf(location)) - return - gravs += gravity - -/datum/component/forced_gravity/proc/turf_gravity_check(datum/source, atom/checker, list/gravs) - return gravity_check(parent, gravs) \ No newline at end of file diff --git a/code/datums/components/material_container.dm b/code/datums/components/material_container.dm index 2f411ff37f..5860bd029b 100644 --- a/code/datums/components/material_container.dm +++ b/code/datums/components/material_container.dm @@ -73,7 +73,7 @@ if(!material_amount) to_chat(user, "[I] does not contain sufficient materials to be accepted by [parent].") return - if(!has_space(material_amount)) + if((!precise_insertion || !GLOB.typecache_stack[I]) && !has_space(material_amount)) to_chat(user, "[parent] has not enough space. Please remove materials from [parent] in order to insert more.") return user_insert(I, user) diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm index 6938046e11..37d77a45bc 100644 --- a/code/datums/components/mood.dm +++ b/code/datums/components/mood.dm @@ -1,40 +1,52 @@ +#define ECSTATIC_SANITY_PEN -1 +#define SLIGHT_INSANITY_PEN 1 #define MINOR_INSANITY_PEN 5 #define MAJOR_INSANITY_PEN 10 +#define MOOD_INSANITY_MALUS 0.13 // 13% debuff per sanity_level above the default of 4 (higher is worser), overall a 39% debuff to skills at rock bottom depression. /datum/component/mood var/mood //Real happiness var/sanity = 100 //Current sanity var/shown_mood //Shown happiness, this is what others can see when they try to examine you, prevents antag checking by noticing traitors are always very happy. var/mood_level = 5 //To track what stage of moodies they're on - var/sanity_level = 5 //To track what stage of sanity they're on + var/sanity_level = 3 //To track what stage of sanity they're on var/mood_modifier = 1 //Modifier to allow certain mobs to be less affected by moodlets var/list/datum/mood_event/mood_events = list() var/insanity_effect = 0 //is the owner being punished for low mood? If so, how much? var/obj/screen/mood/screen_obj + var/datum/skill_modifier/bad_mood/malus + var/datum/skill_modifier/great_mood/bonus + var/static/malus_id = 0 + var/static/list/free_maluses = list() /datum/component/mood/Initialize() if(!isliving(parent)) return COMPONENT_INCOMPATIBLE - START_PROCESSING(SSmood, src) + var/mob/living/owner = parent + if(owner.stat != DEAD) + START_PROCESSING(SSdcs, src) RegisterSignal(parent, COMSIG_ADD_MOOD_EVENT, .proc/add_event) RegisterSignal(parent, COMSIG_CLEAR_MOOD_EVENT, .proc/clear_event) RegisterSignal(parent, COMSIG_MODIFY_SANITY, .proc/modify_sanity) RegisterSignal(parent, COMSIG_LIVING_REVIVE, .proc/on_revive) - RegisterSignal(parent, COMSIG_MOB_HUD_CREATED, .proc/modify_hud) - var/mob/living/owner = parent + RegisterSignal(parent, COMSIG_MOB_DEATH, .proc/stop_processing) + if(owner.hud_used) modify_hud() var/datum/hud/hud = owner.hud_used hud.show_hud(hud.hud_version) /datum/component/mood/Destroy() - STOP_PROCESSING(SSmood, src) + STOP_PROCESSING(SSdcs, src) unmodify_hud() return ..() +/datum/component/mood/proc/stop_processing() + STOP_PROCESSING(SSdcs, src) + /datum/component/mood/proc/print_mood(mob/user) var/msg = "*---------*\nYour current mood\n" msg += "My mental status: " //Long term @@ -126,7 +138,7 @@ else screen_obj.icon_state = "mood[mood_level]" -/datum/component/mood/process() //Called on SSmood process +/datum/component/mood/process() //Called on SSdcs process if(QDELETED(parent)) // workaround to an obnoxious sneaky periodical runtime. qdel(src) return @@ -150,7 +162,7 @@ if(8) setSanity(sanity+0.25, maximum=SANITY_GREAT) if(9) - setSanity(sanity+0.4, maximum=SANITY_GREAT) + setSanity(sanity+0.4, maximum=SANITY_AMAZING) HandleNutrition(owner) @@ -172,6 +184,7 @@ else sanity = amount + var/old_sanity_level = sanity_level switch(sanity) if(-INFINITY to SANITY_CRAZY) setInsanityEffect(MAJOR_INSANITY_PEN) @@ -182,7 +195,7 @@ master.add_movespeed_modifier(/datum/movespeed_modifier/sanity/crazy) sanity_level = 5 if(SANITY_UNSTABLE to SANITY_DISTURBED) - setInsanityEffect(0) + setInsanityEffect(SLIGHT_INSANITY_PEN) master.add_movespeed_modifier(/datum/movespeed_modifier/sanity/disturbed) sanity_level = 4 if(SANITY_DISTURBED to SANITY_NEUTRAL) @@ -194,19 +207,46 @@ master.remove_movespeed_modifier(MOVESPEED_ID_SANITY) sanity_level = 2 if(SANITY_GREAT+1 to INFINITY) - setInsanityEffect(0) + setInsanityEffect(ECSTATIC_SANITY_PEN) //It's not a penalty but w/e master.remove_movespeed_modifier(MOVESPEED_ID_SANITY) sanity_level = 1 + + if(sanity_level != old_sanity_level) + if(sanity_level >= 4) + if(!malus) + if(!length(free_maluses)) + ADD_SKILL_MODIFIER_BODY(/datum/skill_modifier/bad_mood, malus_id++, master, malus) + else + malus = pick_n_take(free_maluses) + if(master.mind) + master.mind.add_skill_modifier(malus.identifier) + else + malus.RegisterSignal(master, COMSIG_MOB_ON_NEW_MIND, /datum/skill_modifier.proc/on_mob_new_mind, TRUE) + malus.value_mod = malus.level_mod = 1 - (sanity_level - 3) * MOOD_INSANITY_MALUS + else if(malus) + if(master.mind) + master.mind.remove_skill_modifier(malus.identifier) + else + malus.UnregisterSignal(master, COMSIG_MOB_ON_NEW_MIND) + free_maluses += malus + malus = null + //update_mood_icon() /datum/component/mood/proc/setInsanityEffect(newval)//More code so that the previous proc works if(newval == insanity_effect) return - //var/mob/living/master = parent - //master.crit_threshold = (master.crit_threshold - insanity_effect) + newval + + var/mob/living/L = parent + if(newval == ECSTATIC_SANITY_PEN && !bonus) + ADD_SKILL_MODIFIER_BODY(/datum/skill_modifier/great_mood, null, L, bonus) + else if(bonus) + REMOVE_SKILL_MODIFIER_BODY(/datum/skill_modifier/great_mood, null, L) + bonus = null + insanity_effect = newval -/datum/component/mood/proc/modify_sanity(datum/source, amount, minimum = -INFINITY, maximum = INFINITY) +/datum/component/mood/proc/modify_sanity(datum/source, amount, minimum = SANITY_INSANE, maximum = SANITY_AMAZING) setSanity(sanity + amount, minimum, maximum) /datum/component/mood/proc/add_event(datum/source, category, type, param) //Category will override any events in the same category, should be unique unless the event is based on the same thing like hunger. @@ -281,12 +321,16 @@ if(0 to NUTRITION_LEVEL_STARVING) add_event(null, "nutrition", /datum/mood_event/starving) -///Called when parent is ahealed. +///Called when parent is revived. /datum/component/mood/proc/on_revive(datum/source, full_heal) + START_PROCESSING(SSdcs, src) if(!full_heal) return remove_temp_moods() setSanity(initial(sanity)) +#undef ECSTATIC_SANITY_PEN +#undef SLIGHT_INSANITY_PEN #undef MINOR_INSANITY_PEN #undef MAJOR_INSANITY_PEN +#undef MOOD_INSANITY_MALUS diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm index 651acda6e1..747dd8ca61 100644 --- a/code/datums/components/riding.dm +++ b/code/datums/components/riding.dm @@ -208,13 +208,13 @@ RegisterSignal(parent, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee) /datum/component/riding/human/vehicle_mob_unbuckle(datum/source, mob/living/M, force = FALSE) - . = ..() var/mob/living/carbon/human/H = parent if(!length(H.buckled_mobs)) H.remove_movespeed_modifier(/datum/movespeed_modifier/human_carry) if(!fireman_carrying) M.Daze(25) REMOVE_TRAIT(M, TRAIT_MOBILITY_NOUSE, src) + return ..() /datum/component/riding/human/vehicle_mob_buckle(datum/source, mob/living/M, force = FALSE) . = ..() diff --git a/code/datums/components/rotation.dm b/code/datums/components/rotation.dm index 6a32a46aef..f5da669c3a 100644 --- a/code/datums/components/rotation.dm +++ b/code/datums/components/rotation.dm @@ -23,18 +23,12 @@ if(can_user_rotate) src.can_user_rotate = can_user_rotate - else - src.can_user_rotate = CALLBACK(src,.proc/default_can_user_rotate) if(can_be_rotated) src.can_be_rotated = can_be_rotated - else - src.can_be_rotated = CALLBACK(src,.proc/default_can_be_rotated) if(after_rotation) src.after_rotation = after_rotation - else - src.after_rotation = CALLBACK(src,.proc/default_after_rotation) //Try Clockwise,counter,flip in order if(src.rotation_flags & ROTATION_FLIP) @@ -103,14 +97,34 @@ examine_list += "Alt-click to rotate it clockwise." /datum/component/simple_rotation/proc/HandRot(datum/source, mob/user, rotation = default_rotation_direction) - if(!can_be_rotated.Invoke(user, rotation) || !can_user_rotate.Invoke(user, rotation)) - return + if(can_be_rotated) + if(!can_be_rotated.Invoke(user, default_rotation_direction)) + return + else + if(!default_can_be_rotated(user, default_rotation_direction)) + return + if(can_user_rotate) + if(!can_user_rotate.Invoke(user, default_rotation_direction)) + return + else + if(!default_can_user_rotate(user, default_rotation_direction)) + return BaseRot(user, rotation) return TRUE /datum/component/simple_rotation/proc/WrenchRot(datum/source, obj/item/I, mob/living/user) - if(!can_be_rotated.Invoke(user,default_rotation_direction) || !can_user_rotate.Invoke(user,default_rotation_direction)) - return + if(can_be_rotated) + if(!can_be_rotated.Invoke(user, default_rotation_direction)) + return + else + if(!default_can_be_rotated(user, default_rotation_direction)) + return + if(can_user_rotate) + if(!can_user_rotate.Invoke(user, default_rotation_direction)) + return + else + if(!default_can_user_rotate(user, default_rotation_direction)) + return if(istype(I,/obj/item/wrench)) BaseRot(user,default_rotation_direction) return COMPONENT_NO_AFTERATTACK @@ -126,7 +140,10 @@ if(ROTATION_FLIP) rot_degree = 180 AM.setDir(turn(AM.dir,rot_degree)) - after_rotation.Invoke(user,rotation_type) + if(after_rotation) + after_rotation.Invoke(user, rotation_type) + else + default_after_rotation(user, rotation_type) /datum/component/simple_rotation/proc/default_can_user_rotate(mob/living/user, rotation_type) if(!istype(user) || !user.canUseTopic(parent, BE_CLOSE, NO_DEXTERY)) diff --git a/code/datums/components/storage/concrete/_concrete.dm b/code/datums/components/storage/concrete/_concrete.dm index e044a59668..55c3e1d083 100644 --- a/code/datums/components/storage/concrete/_concrete.dm +++ b/code/datums/components/storage/concrete/_concrete.dm @@ -136,9 +136,7 @@ var/mob/M = parent.loc I.dropped(M) if(new_location) - //Reset the items values - _removal_reset(AM) - AM.forceMove(new_location) + AM.forceMove(new_location) // exited comsig will handle removal reset. //We don't want to call this if the item is being destroyed AM.on_exit_storage(src) else diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index aad6e8289f..f93d40bb04 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -351,10 +351,14 @@ return master._removal_reset(thing) /datum/component/storage/proc/_remove_and_refresh(datum/source, atom/movable/thing) - _removal_reset(thing) if(LAZYACCESS(ui_item_blocks, thing)) - qdel(ui_item_blocks[thing]) + var/obj/screen/storage/volumetric_box/center/C = ui_item_blocks[thing] + for(var/i in can_see_contents()) //runtimes result if mobs can access post deletion. + var/mob/M = i + M.client?.screen -= C.on_screen_objects() ui_item_blocks -= thing + qdel(C) + _removal_reset(thing) // THIS NEEDS TO HAPPEN AFTER SO LAYERING DOESN'T BREAK! refresh_mob_views() //Call this proc to handle the removal of an item from the storage item. The item will be moved to the new_location target, if that is null it's being deleted @@ -567,10 +571,9 @@ return if(rustle_sound) playsound(parent, "rustle", 50, 1, -5) - for(var/mob/viewing in viewers(user, null)) - if(M == viewing) - to_chat(usr, "You put [I] [insert_preposition]to [parent].") - else if(in_range(M, viewing)) //If someone is standing close enough, they can tell what it is... + to_chat(user, "You put [I] [insert_preposition]to [parent].") + for(var/mob/viewing in fov_viewers(world.view, user)-M) + if(in_range(M, viewing)) //If someone is standing close enough, they can tell what it is... viewing.show_message("[M] puts [I] [insert_preposition]to [parent].", MSG_VISUAL) else if(I && I.w_class >= 3) //Otherwise they can only see large or normal items from a distance... viewing.show_message("[M] puts [I] [insert_preposition]to [parent].", MSG_VISUAL) diff --git a/code/datums/components/storage/ui.dm b/code/datums/components/storage/ui.dm index f37f574002..c7ac0d3549 100644 --- a/code/datums/components/storage/ui.dm +++ b/code/datums/components/storage/ui.dm @@ -92,6 +92,8 @@ var/list/volume_by_item = list() var/list/percentage_by_item = list() for(var/obj/item/I in contents) + if(QDELETED(I)) + continue volume = I.get_w_volume() used += volume volume_by_item[I] = volume @@ -123,6 +125,7 @@ var/obj/item/I // start at this pixel from screen_start_x. var/current_pixel = VOLUMETRIC_STORAGE_EDGE_PADDING + var/first = TRUE var/row = 1 LAZYINITLIST(ui_item_blocks) @@ -140,10 +143,10 @@ addrow = TRUE // now that we have pixels_to_use, place our thing and add it to the returned list. - - B.screen_loc = I.screen_loc = "[screen_start_x]:[round(current_pixel + (pixels_to_use * 0.5) + VOLUMETRIC_STORAGE_ITEM_PADDING, 1)],[screen_start_y+row-1]:[screen_pixel_y]" + B.screen_loc = I.screen_loc = "[screen_start_x]:[round(current_pixel + (pixels_to_use * 0.5) + (first? 0 : VOLUMETRIC_STORAGE_ITEM_PADDING), 1)],[screen_start_y+row-1]:[screen_pixel_y]" // add the used pixels to pixel after we place the object - current_pixel += pixels_to_use + VOLUMETRIC_STORAGE_ITEM_PADDING + current_pixel += pixels_to_use + (first? 0 : VOLUMETRIC_STORAGE_ITEM_PADDING) + first = FALSE //apply padding to everything after this // set various things B.set_pixel_size(pixels_to_use) @@ -163,6 +166,7 @@ // go up a row if needed if(addrow) row++ + first = TRUE //first in the row, don't apply between-item padding. current_pixel = VOLUMETRIC_STORAGE_EDGE_PADDING // Then, continuous section. @@ -233,7 +237,7 @@ if(!M.client) return TRUE UnregisterSignal(M, COMSIG_MOB_CLIENT_LOGOUT) - M.client.screen -= list(ui_boxes, ui_close, ui_left, ui_continuous) + get_ui_item_objects_hide() + M.client.screen -= list(ui_boxes, ui_close, ui_left, ui_continuous) + get_ui_item_objects_hide(M) if(M.active_storage == src) M.active_storage = null LAZYREMOVE(is_using, M) @@ -249,8 +253,8 @@ /** * Gets the ui item objects to ui_hide. */ -/datum/component/storage/proc/get_ui_item_objects_hide() - if(!volumetric_ui()) +/datum/component/storage/proc/get_ui_item_objects_hide(mob/M) + if(!volumetric_ui() || M.client?.prefs?.no_tetris_storage) var/atom/real_location = real_location() return real_location.contents else diff --git a/code/datums/components/tactical.dm b/code/datums/components/tactical.dm deleted file mode 100644 index b73c58604a..0000000000 --- a/code/datums/components/tactical.dm +++ /dev/null @@ -1,44 +0,0 @@ - -/datum/component/tactical - var/allowed_slot - -/datum/component/tactical/Initialize(allowed_slot) - if(!isitem(parent)) - return COMPONENT_INCOMPATIBLE - - src.allowed_slot = allowed_slot - -/datum/component/tactical/RegisterWithParent() - . = ..() - RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/modify) - RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/unmodify) - -/datum/component/tactical/UnregisterFromParent() - . = ..() - UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED)) - unmodify() - -/datum/component/tactical/Destroy() - unmodify() - return ..() - -/datum/component/tactical/proc/modify(obj/item/source, mob/user, slot) - if(allowed_slot && slot != allowed_slot) - unmodify() - return - - var/obj/item/master = parent - var/image/I = image(icon = master.icon, icon_state = master.icon_state, loc = user) - I.copy_overlays(master) - I.override = TRUE - source.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "sneaking_mission", I) - I.layer = ABOVE_MOB_LAYER - -/datum/component/tactical/proc/unmodify(obj/item/source, mob/user) - var/obj/item/master = source || parent - if(!user) - if(!ismob(master.loc)) - return - user = master.loc - - user.remove_alt_appearance("sneaking_mission") diff --git a/code/datums/diseases/_MobProcs.dm b/code/datums/diseases/_MobProcs.dm index a7a61802d3..216d82b4c8 100644 --- a/code/datums/diseases/_MobProcs.dm +++ b/code/datums/diseases/_MobProcs.dm @@ -145,4 +145,10 @@ return !is_mouth_covered() /mob/living/carbon/CanSpreadAirborneDisease() - return !((head && (head.flags_cover & HEADCOVERSMOUTH) && (head.armor.getRating("bio") >= 25)) || (wear_mask && (wear_mask.flags_cover & MASKCOVERSMOUTH) && (wear_mask.armor.getRating("bio") >= 25))) \ No newline at end of file + return !((head && (head.flags_cover & HEADCOVERSMOUTH) && (head.armor.getRating("bio") >= 25)) || (wear_mask && (wear_mask.flags_cover & MASKCOVERSMOUTH) && (wear_mask.armor.getRating("bio") >= 25))) + +/mob/living/proc/set_shocked() + flags_1 |= SHOCKED_1 + +/mob/living/proc/reset_shocked() + flags_1 &= ~ SHOCKED_1 \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index 59afe163b4..787704e848 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -126,7 +126,7 @@ var/datum/reagent/R = E M.reagents.remove_reagent(R.type, actual_power) if(food_conversion) - M.nutrition += 0.3 + M.adjust_nutrition(0.3) if(prob(2)) to_chat(M, "You feel a mild warmth as your blood purifies itself.") return 1 @@ -164,7 +164,7 @@ C.reagents.metabolize(C, can_overdose=TRUE) C.overeatduration = max(C.overeatduration - 2, 0) var/lost_nutrition = 9 - (reduced_hunger * 5) - C.nutrition = max(C.nutrition - (lost_nutrition * HUNGER_FACTOR), 0) //Hunger depletes at 10x the normal speed + C.adjust_nutrition(-lost_nutrition * HUNGER_FACTOR) //Hunger depletes at 10x the normal speed if(prob(2)) to_chat(C, "You feel an odd gurgle in your stomach, as if it was working much faster than normal.") return 1 @@ -454,7 +454,7 @@ "Transmission 6" = "Additionally heals cellular damage and toxin lovers.", "Resistance 7" = "Increases healing speed.", ) - + /datum/symptom/heal/radiation/Start(datum/disease/advance/A) if(!..()) return diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm index bbacdd885d..79966b8f54 100644 --- a/code/datums/diseases/advance/symptoms/sensory.dm +++ b/code/datums/diseases/advance/symptoms/sensory.dm @@ -58,7 +58,7 @@ var/mob/living/carbon/C = M if(prob(10)) if(trauma_heal_severe) - C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_LOBOTOMY) + C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_SURGERY) else C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_BASIC) diff --git a/code/datums/diseases/advance/symptoms/voice_change.dm b/code/datums/diseases/advance/symptoms/voice_change.dm index 9be484d99a..9fa6ed5cc8 100644 --- a/code/datums/diseases/advance/symptoms/voice_change.dm +++ b/code/datums/diseases/advance/symptoms/voice_change.dm @@ -30,7 +30,6 @@ Bonus symptom_delay_max = 120 var/scramble_language = FALSE var/datum/language/current_language - var/datum/language_holder/original_language threshold_desc = list( "Transmission 14" = "The host's language center of the brain is damaged, leading to complete inability to speak or understand any language.", "Stage Speed 7" = "Changes voice more often.", @@ -48,9 +47,6 @@ Bonus symptom_delay_max = 85 if(A.properties["transmittable"] >= 14) //random language scramble_language = TRUE - var/mob/living/M = A.affected_mob - var/datum/language_holder/mob_language = M.get_language_holder() - original_language = mob_language.copy() /datum/symptom/voice_change/Activate(datum/disease/advance/A) if(!..()) @@ -64,12 +60,10 @@ Bonus if(ishuman(M)) var/mob/living/carbon/human/H = M H.SetSpecialVoice(H.dna.species.random_name(H.gender)) - if(scramble_language) - H.remove_language(current_language) + if(scramble_language && !current_language) // Last part prevents rerolling language with small amounts of cure. current_language = pick(subtypesof(/datum/language) - /datum/language/common) - H.grant_language(current_language) - var/datum/language_holder/mob_language = H.get_language_holder() - mob_language.only_speaks_language = current_language + H.add_blocked_language(subtypesof(/datum/language) - current_language, LANGUAGE_VOICECHANGE) + H.grant_language(current_language, TRUE, TRUE, LANGUAGE_VOICECHANGE) /datum/symptom/voice_change/End(datum/disease/advance/A) ..() @@ -77,7 +71,5 @@ Bonus var/mob/living/carbon/human/H = A.affected_mob H.UnsetSpecialVoice() if(scramble_language) - var/mob/living/M = A.affected_mob - M.copy_known_languages_from(original_language, TRUE) - current_language = null - QDEL_NULL(original_language) + A.affected_mob.remove_blocked_language(subtypesof(/datum/language), LANGUAGE_VOICECHANGE) + A.affected_mob.remove_all_languages(LANGUAGE_VOICECHANGE) // In case someone managed to get more than one anyway. diff --git a/code/datums/diseases/advance/symptoms/weight.dm b/code/datums/diseases/advance/symptoms/weight.dm index 5eab698750..bb0d9bdcf9 100644 --- a/code/datums/diseases/advance/symptoms/weight.dm +++ b/code/datums/diseases/advance/symptoms/weight.dm @@ -50,4 +50,4 @@ Bonus else to_chat(M, "[pick("So hungry...", "You'd kill someone for a bite of food...", "Hunger cramps seize you...")]") M.overeatduration = max(M.overeatduration - 100, 0) - M.nutrition = max(M.nutrition - 100, 0) \ No newline at end of file + M.adjust_nutrition(-100) \ No newline at end of file diff --git a/code/datums/diseases/tuberculosis.dm b/code/datums/diseases/tuberculosis.dm index 23902603ce..f59a19c7a3 100644 --- a/code/datums/diseases/tuberculosis.dm +++ b/code/datums/diseases/tuberculosis.dm @@ -52,7 +52,7 @@ if(prob(3)) to_chat(affected_mob, "[pick("Your stomach silently rumbles...", "Your stomach seizes up and falls limp, muscles dead and lifeless.", "You could eat a crayon")]") affected_mob.overeatduration = max(affected_mob.overeatduration - 100, 0) - affected_mob.nutrition = max(affected_mob.nutrition - 100, 0) + affected_mob.adjust_nutrition(-100) if(prob(15)) to_chat(affected_mob, "[pick("You feel uncomfortably hot...", "You feel like unzipping your jumpsuit", "You feel like taking off some clothes...")]") affected_mob.adjust_bodytemperature(40) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index e0df2a8f1b..747db3d6ce 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -47,8 +47,8 @@ destination.dna.uni_identity = uni_identity destination.dna.blood_type = blood_type destination.dna.skin_tone_override = skin_tone_override - destination.set_species(species.type, icon_update=0) destination.dna.features = features.Copy() + destination.set_species(species.type, icon_update=0) destination.dna.real_name = real_name destination.dna.nameless = nameless destination.dna.custom_species = custom_species @@ -152,10 +152,11 @@ return . /datum/dna/proc/generate_dna_blocks() - var/bonus + var/list/mutations_temp = GLOB.good_mutations + GLOB.bad_mutations + GLOB.not_good_mutations if(species && species.inert_mutation) - bonus = GET_INITIALIZED_MUTATION(species.inert_mutation) - var/list/mutations_temp = GLOB.good_mutations + GLOB.bad_mutations + GLOB.not_good_mutations + bonus + var/bonus = GET_INITIALIZED_MUTATION(species.inert_mutation) + if(bonus) + mutations_temp += bonus if(!LAZYLEN(mutations_temp)) return mutation_index.Cut() @@ -245,6 +246,17 @@ construct_block(GLOB.mam_body_markings_list.Find(features["mam_body_markings"]), GLOB.mam_body_markings_list.len) if(DNA_TAUR_BLOCK) construct_block(GLOB.taur_list.Find(features["taur"]), GLOB.taur_list.len) + if(species.mutant_bodyparts["taur"] && ishuman(holder)) + var/datum/sprite_accessory/taur/T = GLOB.taur_list[features["taur"]] + switch(T?.taur_mode) + if(STYLE_HOOF_TAURIC) + H.physiology.footstep_type = FOOTSTEP_MOB_SHOE + if(STYLE_PAW_TAURIC) + H.physiology.footstep_type = FOOTSTEP_MOB_CLAW + if(STYLE_SNEK_TAURIC) + H.physiology.footstep_type = FOOTSTEP_MOB_CRAWL + else + H.physiology.footstep_type = null //Please use add_mutation or activate_mutation instead /datum/dna/proc/force_give(datum/mutation/human/HM) @@ -355,6 +367,11 @@ var/datum/species/old_species = dna.species dna.species = new_race dna.species.on_species_gain(src, old_species, pref_load) + if(ishuman(src)) + qdel(language_holder) + var/species_holder = initial(mrace.species_language_holder) + language_holder = new species_holder(src) + update_atom_languages() /mob/living/carbon/human/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE) ..() diff --git a/code/datums/elements/dwarfism.dm b/code/datums/elements/dwarfism.dm new file mode 100644 index 0000000000..fefbe4fbe7 --- /dev/null +++ b/code/datums/elements/dwarfism.dm @@ -0,0 +1,42 @@ +#define SHORT 4/5 +#define TALL 5/4 + +///Very similar to squish, but for dwarves and shorties +/datum/element/dwarfism + element_flags = ELEMENT_DETACH|ELEMENT_BESPOKE + id_arg_index = 2 + var/comsig + var/list/attached_targets = list() + +/datum/element/dwarfism/Attach(datum/target, comsig, comsig_target) + . = ..() + if(!isliving(target)) + return ELEMENT_INCOMPATIBLE + + src.comsig = comsig + + var/mob/living/L = target + if(L.lying != 0) + L.transform = L.transform.Scale(SHORT, 1) + else + L.transform = L.transform.Scale(1, SHORT) + attached_targets[target] = comsig_target + RegisterSignal(target, comsig, .proc/check_loss) //Second arg of the signal will be checked against the comsig_target. + +/datum/element/dwarfism/proc/check_loss(mob/living/L, comsig_target) + if(attached_targets[L] == comsig_target) + Detach(L) + +/datum/element/dwarfism/Detach(mob/living/L) + . = ..() + if(QDELETED(L)) + return + if(L.lying != 0) + L.transform = L.transform.Scale(TALL, 1) + else + L.transform = L.transform.Scale(1, TALL) + UnregisterSignal(L, comsig) + attached_targets -= L + +#undef SHORT +#undef TALL diff --git a/code/datums/elements/empprotection.dm b/code/datums/elements/empprotection.dm new file mode 100644 index 0000000000..c24914decb --- /dev/null +++ b/code/datums/elements/empprotection.dm @@ -0,0 +1,18 @@ +/datum/element/empprotection + element_flags = ELEMENT_DETACH | ELEMENT_BESPOKE + id_arg_index = 2 + var/flags = NONE + +/datum/element/empprotection/Attach(datum/target, _flags) + . = ..() + if(. == ELEMENT_INCOMPATIBLE || !isatom(target)) + return ELEMENT_INCOMPATIBLE + flags = _flags + RegisterSignal(target, COMSIG_ATOM_EMP_ACT, .proc/getEmpFlags) + +/datum/element/empprotection/Detach(atom/target) + UnregisterSignal(target, COMSIG_ATOM_EMP_ACT) + return ..() + +/datum/element/empprotection/proc/getEmpFlags(datum/source, severity) + return flags diff --git a/code/datums/elements/flavor_text.dm b/code/datums/elements/flavor_text.dm index e9d8f278f4..f44215d9ac 100644 --- a/code/datums/elements/flavor_text.dm +++ b/code/datums/elements/flavor_text.dm @@ -5,12 +5,16 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code id_arg_index = 3 var/flavor_name = "Flavor Text" var/list/texts_by_atom = list() - var/addendum = "This can also be used for OOC notes and preferences!" + var/addendum = "" var/always_show = FALSE var/max_len = MAX_FLAVOR_LEN var/can_edit = TRUE + /// For preference/DNA saving/loading. Null to prevent. Prefs are only loaded from obviously if it exists in preferences.features. + var/save_key + /// Do not attempt to render a preview on examine. If this is on, it will display as \[flavor_name\] + var/examine_no_preview = FALSE -/datum/element/flavor_text/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FLAVOR_LEN, _always_show = FALSE, _edit = TRUE) +/datum/element/flavor_text/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FLAVOR_LEN, _always_show = FALSE, _edit = TRUE, _save_key, _examine_no_preview = FALSE) . = ..() if(. == ELEMENT_INCOMPATIBLE || !isatom(target)) //no reason why this shouldn't work on atoms too. @@ -25,6 +29,8 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code addendum = _addendum always_show = _always_show can_edit = _edit + save_key = _save_key + examine_no_preview = _examine_no_preview RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/show_flavor) @@ -33,9 +39,12 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code LAZYOR(GLOB.mobs_with_editable_flavor_text[M], src) M.verbs |= /mob/proc/manage_flavor_tests + if(save_key && ishuman(target)) + RegisterSignal(target, COMSIG_HUMAN_PREFS_COPIED_TO, .proc/update_prefs_flavor_text) + /datum/element/flavor_text/Detach(atom/A) . = ..() - UnregisterSignal(A, COMSIG_PARENT_EXAMINE) + UnregisterSignal(A, list(COMSIG_PARENT_EXAMINE, COMSIG_HUMAN_PREFS_COPIED_TO)) texts_by_atom -= A if(can_edit && ismob(A)) var/mob/M = A @@ -58,6 +67,9 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code var/text = texts_by_atom[target] if(!text) return + if(examine_no_preview) + examine_list += "\[[flavor_name]\]" + return var/msg = replacetext(text, "\n", " ") if(length_char(msg) <= 40) examine_list += "[msg]" @@ -112,13 +124,17 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code return TRUE return FALSE +/datum/element/flavor_text/proc/update_prefs_flavor_text(mob/living/carbon/human/H, datum/preferences/P, icon_updates = TRUE, roundstart_checks = TRUE) + if(P.features.Find(save_key)) + texts_by_atom[H] = P.features[save_key] + //subtypes with additional hooks for DNA and preferences. /datum/element/flavor_text/carbon //list of antagonists etcetera that should have nothing to do with people's snowflakes. var/static/list/i_dont_even_know_who_you_are = typecacheof(list(/datum/antagonist/abductor, /datum/antagonist/ert, /datum/antagonist/nukeop, /datum/antagonist/wizard)) -/datum/element/flavor_text/carbon/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FLAVOR_LEN, _always_show = FALSE, _edit = TRUE) +/datum/element/flavor_text/carbon/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FLAVOR_LEN, _always_show = FALSE, _edit = TRUE, _save_key = "flavor_text", _examine_no_preview = FALSE) if(!iscarbon(target)) return ELEMENT_INCOMPATIBLE . = ..() @@ -127,7 +143,6 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code RegisterSignal(target, COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, .proc/update_dna_flavor_text) RegisterSignal(target, COMSIG_MOB_ANTAG_ON_GAIN, .proc/on_antag_gain) if(ishuman(target)) - RegisterSignal(target, COMSIG_HUMAN_PREFS_COPIED_TO, .proc/update_prefs_flavor_text) RegisterSignal(target, COMSIG_HUMAN_HARDSET_DNA, .proc/update_dna_flavor_text) RegisterSignal(target, COMSIG_HUMAN_ON_RANDOMIZE, .proc/unset_flavor) @@ -136,15 +151,12 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code UnregisterSignal(C, list(COMSIG_CARBON_IDENTITY_TRANSFERRED_TO, COMSIG_MOB_ANTAG_ON_GAIN, COMSIG_HUMAN_PREFS_COPIED_TO, COMSIG_HUMAN_HARDSET_DNA, COMSIG_HUMAN_ON_RANDOMIZE)) /datum/element/flavor_text/carbon/proc/update_dna_flavor_text(mob/living/carbon/C) - texts_by_atom[C] = C.dna.features["flavor_text"] - -/datum/element/flavor_text/carbon/proc/update_prefs_flavor_text(mob/living/carbon/human/H, datum/preferences/P, icon_updates = TRUE, roundstart_checks = TRUE) - texts_by_atom[H] = P.features["flavor_text"] + texts_by_atom[C] = C.dna.features[save_key] /datum/element/flavor_text/carbon/set_flavor(mob/living/carbon/user) . = ..() if(. && user.dna) - user.dna.features["flavor_text"] = texts_by_atom[user] + user.dna.features[save_key] = texts_by_atom[user] /datum/element/flavor_text/carbon/proc/unset_flavor(mob/living/carbon/user) texts_by_atom[user] = "" @@ -153,4 +165,4 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code if(is_type_in_typecache(antag, i_dont_even_know_who_you_are)) texts_by_atom[user] = "" if(user.dna) - user.dna.features["flavor_text"] = "" \ No newline at end of file + user.dna.features[save_key] = "" diff --git a/code/datums/elements/forced_gravity.dm b/code/datums/elements/forced_gravity.dm new file mode 100644 index 0000000000..0b50df5b21 --- /dev/null +++ b/code/datums/elements/forced_gravity.dm @@ -0,0 +1,30 @@ +/datum/element/forced_gravity + element_flags = ELEMENT_BESPOKE + id_arg_index = 2 + var/gravity + var/ignore_space + +/datum/element/forced_gravity/Attach(datum/target, gravity=1, ignore_space=FALSE) + . = ..() + if(!isatom(target)) + return ELEMENT_INCOMPATIBLE + + src.gravity = gravity + src.ignore_space = ignore_space + + RegisterSignal(target, COMSIG_ATOM_HAS_GRAVITY, .proc/gravity_check) + if(isturf(target)) + RegisterSignal(target, COMSIG_TURF_HAS_GRAVITY, .proc/turf_gravity_check) + +/datum/element/forced_gravity/Detach(datum/source, force) + . = ..() + var/static/list/signals_b_gone = list(COMSIG_ATOM_HAS_GRAVITY, COMSIG_TURF_HAS_GRAVITY) + UnregisterSignal(source, signals_b_gone) + +/datum/element/forced_gravity/proc/gravity_check(datum/source, turf/location, list/gravs) + if(!ignore_space && isspaceturf(location)) + return + gravs += gravity + +/datum/element/forced_gravity/proc/turf_gravity_check(datum/source, atom/checker, list/gravs) + return gravity_check(null, source, gravs) diff --git a/code/datums/elements/tactical.dm b/code/datums/elements/tactical.dm new file mode 100644 index 0000000000..c74850795b --- /dev/null +++ b/code/datums/elements/tactical.dm @@ -0,0 +1,37 @@ +/datum/element/tactical + element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH + id_arg_index = 2 + var/allowed_slot + +/datum/element/tactical/Attach(datum/target, allowed_slot) + . = ..() + if(. == ELEMENT_INCOMPATIBLE || !isitem(target)) + return ELEMENT_INCOMPATIBLE + + src.allowed_slot = allowed_slot + RegisterSignal(target, COMSIG_ITEM_EQUIPPED, .proc/modify) + RegisterSignal(target, COMSIG_ITEM_DROPPED, .proc/unmodify) + +/datum/element/tactical/Detach(datum/target) + UnregisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED)) + unmodify() + return ..() + +/datum/element/tactical/proc/modify(obj/item/source, mob/user, slot) + if(allowed_slot && slot != allowed_slot) + unmodify() + return + + var/image/I = image(icon = source.icon, icon_state = source.icon_state, loc = user) + I.copy_overlays(source) + I.override = TRUE + source.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "sneaking_mission", I) + I.layer = ABOVE_MOB_LAYER + +/datum/element/tactical/proc/unmodify(obj/item/source, mob/user) + if(!user) + if(!ismob(source.loc)) + return + user = source.loc + + user.remove_alt_appearance("sneaking_mission") diff --git a/code/datums/elements/wuv.dm b/code/datums/elements/wuv.dm index fffb90c681..6476a204cf 100644 --- a/code/datums/elements/wuv.dm +++ b/code/datums/elements/wuv.dm @@ -41,7 +41,7 @@ return //we want to delay the effect to be displayed after the mob is petted, not before. switch(user.a_intent) - if(INTENT_HARM, INTENT_DISARM) + if(INTENT_HARM) addtimer(CALLBACK(src, .proc/kick_the_dog, source, user), 1) if(INTENT_HELP) addtimer(CALLBACK(src, .proc/pet_the_dog, source, user), 1) diff --git a/code/datums/explosion.dm b/code/datums/explosion.dm index f763affcd1..dc32902e5e 100644 --- a/code/datums/explosion.dm +++ b/code/datums/explosion.dm @@ -76,7 +76,9 @@ GLOBAL_LIST_EMPTY(explosions) //I would make this not ex_act the thing that triggered the explosion, //but everything that explodes gives us their loc or a get_turf() //and somethings expect us to ex_act them so they can qdel() - stoplag() //tldr, let the calling proc call qdel(src) before we explode + //stoplag() //tldr, let the calling proc call qdel(src) before we explode + // no - use sleep. stoplag() results in quirky things like explosions taking too long to process and hanging mid-air for no reason. + sleep(0) EX_PREPROCESS_EXIT_CHECK diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm index 0b0fed407c..91b8e32566 100644 --- a/code/datums/helper_datums/getrev.dm +++ b/code/datums/helper_datums/getrev.dm @@ -5,16 +5,18 @@ var/list/testmerge = list() /datum/getrev/New() + commit = rustg_git_revparse("HEAD") + if(commit) + date = rustg_git_commit_date(commit) + originmastercommit = rustg_git_revparse("origin/master") + +/datum/getrev/proc/load_tgs_info() testmerge = world.TgsTestMerges() var/datum/tgs_revision_information/revinfo = world.TgsRevision() if(revinfo) commit = revinfo.commit originmastercommit = revinfo.origin_commit - else - commit = rustg_git_revparse("HEAD") - if(commit) - date = rustg_git_commit_date(commit) - originmastercommit = rustg_git_revparse("origin/master") + date = rustg_git_commit_date(commit) // goes to DD log and config_error.txt log_world(get_log_message()) @@ -77,7 +79,9 @@ msg += "No commit information" if(world.TgsAvailable()) var/datum/tgs_version/version = world.TgsVersion() - msg += "Server tools version: [version.raw_parameter]" + msg += "TGS version: [version.raw_parameter]" + var/datum/tgs_version/api_version = world.TgsApiVersion() + msg += "DMAPI version: [api_version.raw_parameter]" // Game mode odds msg += "
Current Informational Settings:" @@ -121,4 +125,4 @@ if(probabilities[ctag] > 0) var/percentage = round(probabilities[ctag] / sum * 100, 0.1) msg += "[ctag] [percentage]%" - to_chat(src, msg.Join("
")) \ No newline at end of file + to_chat(src, msg.Join("
")) diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index f07b1d8792..f189a91353 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -72,7 +72,7 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/uranium/on_applied(atom/source, amount, material_flags) . = ..() - source.AddComponent(/datum/component/radioactive, amount / 20, source, 0) //half-life of 0 because we keep on going. + source.AddComponent(/datum/component/radioactive, amount / 60, source, 0) //half-life of 0 because we keep on going. /datum/material/uranium/on_removed(atom/source, material_flags) . = ..() diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 728c4fb51b..b7eac62e83 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -67,7 +67,7 @@ var/datum/skill_holder/skill_holder /datum/mind/New(var/key) - skill_holder = new + skill_holder = new() src.key = key soulOwner = src martial_art = default_martial_art @@ -80,12 +80,12 @@ if(antag_datum.delete_on_mind_deletion) qdel(i) antag_datums = null + QDEL_NULL(skill_holder) return ..() /datum/mind/proc/get_language_holder() if(!language_holder) - var/datum/language_holder/L = current.get_language_holder(shadow=FALSE) - language_holder = L.copy(src) + language_holder = new (src) return language_holder @@ -100,9 +100,6 @@ if(iscarbon(current)) var/mob/living/carbon/C = current C.disable_intentional_combat_mode(TRUE) - if(!language_holder) - var/datum/language_holder/mob_holder = new_character.get_language_holder(shadow = FALSE) - language_holder = mob_holder.copy(src) if(key) if(new_character.key != key) //if we're transferring into a body with a key associated which is not ours @@ -130,6 +127,7 @@ transfer_martial_arts(new_character) if(active || force_key_move) new_character.key = key //now transfer the key to link the client to our new body + current.update_atom_languages() //CIT CHANGE - makes arousal update when transfering bodies if(isliving(new_character)) //New humans and such are by default enabled arousal. Let's always use the new mind's prefs. diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index 1464927c3a..c56425b074 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -248,7 +248,7 @@ description = "Something I recently ate was horrifyingly disgusting.\n" mood_change = -5 timeout = 5 MINUTES - + /datum/mood_event/nanite_sadness description = "+++++++HAPPINESS SUPPRESSION+++++++\n" mood_change = -7 @@ -256,3 +256,7 @@ /datum/mood_event/nanite_sadness/add_effects(message) description = "+++++++[message]+++++++\n" +/datum/mood_event/artbad + description = "I've produced better art than that from my ass.\n" + mood_change = -2 + timeout = 1200 diff --git a/code/datums/mood_events/generic_positive_events.dm b/code/datums/mood_events/generic_positive_events.dm index 1e9a53cf57..95177f6869 100644 --- a/code/datums/mood_events/generic_positive_events.dm +++ b/code/datums/mood_events/generic_positive_events.dm @@ -182,3 +182,17 @@ description = "What a peculiar emblem. It makes me feel hopeful for my future.\n" mood_change = 5 +/datum/mood_event/artok + description = "It's nice to see people are making art around here.\n" + mood_change = 2 + timeout = 2 MINUTES + +/datum/mood_event/artgood + description = "What a thought-provoking piece of art. I'll remember that for a while.\n" + mood_change = 3 + timeout = 3 MINUTES + +/datum/mood_event/artgreat + description = "That work of art was so great it made me believe in the goodness of humanity. Says a lot in a place like this.\n" + mood_change = 4 + timeout = 4 MINUTES diff --git a/code/datums/mutations/_mutations.dm b/code/datums/mutations/_mutations.dm index 9edaa7605c..db739c5100 100644 --- a/code/datums/mutations/_mutations.dm +++ b/code/datums/mutations/_mutations.dm @@ -116,7 +116,8 @@ owner.apply_overlay(layer_used) if(power) owner.RemoveSpell(power) - qdel(src) + qdel(power) + SEND_SIGNAL(owner, COMSIG_HUMAN_MUTATION_LOSS, src) return 0 return 1 diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm index 9f8c74e2db..866ea85dbf 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -82,7 +82,7 @@ if(..()) return ADD_TRAIT(owner, TRAIT_DWARF, GENETIC_MUTATION) - owner.transform = owner.transform.Scale(1, 0.8) + owner.AddElement(/datum/element/dwarfism, COMSIG_HUMAN_MUTATION_LOSS, src) passtable_on(owner, GENETIC_MUTATION) owner.visible_message("[owner] suddenly shrinks!", "Everything around you seems to grow..") @@ -90,7 +90,6 @@ if(..()) return REMOVE_TRAIT(owner, TRAIT_DWARF, GENETIC_MUTATION) - owner.transform = owner.transform.Scale(1, 1.25) passtable_off(owner, GENETIC_MUTATION) owner.visible_message("[owner] suddenly grows!", "Everything around you seems to shrink..") diff --git a/code/datums/mutations/speech.dm b/code/datums/mutations/speech.dm index e474272326..d4db7e34c2 100644 --- a/code/datums/mutations/speech.dm +++ b/code/datums/mutations/speech.dm @@ -277,10 +277,10 @@ /datum/mutation/human/stoner/on_acquiring(mob/living/carbon/human/owner) ..() - owner.grant_language(/datum/language/beachbum) - owner.remove_language(/datum/language/common) + owner.grant_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_STONER) + owner.add_blocked_language(subtypesof(/datum/language) - /datum/language/beachbum, LANGUAGE_STONER) /datum/mutation/human/stoner/on_losing(mob/living/carbon/human/owner) ..() - owner.grant_language(/datum/language/common) - owner.remove_language(/datum/language/beachbum) + owner.remove_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_STONER) + owner.remove_blocked_language(subtypesof(/datum/language) - /datum/language/beachbum, LANGUAGE_STONER) diff --git a/code/datums/position_point_vector.dm b/code/datums/position_point_vector.dm index 608683c3dc..482e15c57d 100644 --- a/code/datums/position_point_vector.dm +++ b/code/datums/position_point_vector.dm @@ -189,6 +189,12 @@ x += mpx * (multiplier) y += mpy * (multiplier) +/datum/point/vector/proc/pixel_increment(pixels = 32, update_iteration = TRUE, realistic_iteration = FALSE) + if(update_iteration) + iteration += realistic_iteration? round(pixels / speed) : 1 + x += sin(angle) * pixels + y += cos(angle) * pixels + /datum/point/vector/proc/return_vector_after_increments(amount = 7, multiplier = 1, force_simulate = FALSE) var/datum/point/vector/v = copy_to() if(force_simulate) diff --git a/code/datums/skills/_check_skills.dm b/code/datums/skills/_check_skills.dm index d9dc6dad3d..a94c7c95ba 100644 --- a/code/datums/skills/_check_skills.dm +++ b/code/datums/skills/_check_skills.dm @@ -12,5 +12,5 @@ to_chat(usr, "How do you check the skills of [(usr == src)? "yourself when you are" : "something"] without the capability for skills? (PROBABLY A BUG, PRESS F1.)") return var/datum/browser/B = new(usr, "skilldisplay_[REF(src)]", "Skills of [src]") - B.set_content(mind.skill_holder.html_readout()) + B.set_content(mind.skill_html_readout()) B.open() diff --git a/code/datums/skills/_skill.dm b/code/datums/skills/_skill.dm index 2dd321c4c6..571a8274d8 100644 --- a/code/datums/skills/_skill.dm +++ b/code/datums/skills/_skill.dm @@ -1,4 +1,4 @@ -GLOBAL_LIST_INIT(skill_datums, init_skill_datums()) +GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) /proc/init_skill_datums() . = list() @@ -9,31 +9,31 @@ GLOBAL_LIST_INIT(skill_datums, init_skill_datums()) S = new path .[S.type] = S -/proc/get_skill_datum(path) - return GLOB.skill_datums[path] - -/proc/sanitize_skill_value(path, value) - var/datum/skill/S = get_skill_datum(path) - // don't check, if we runtime let it happen. - return S.sanitize_value(value) - -/proc/is_skill_value_greater(path, existing, new_value) - var/datum/skill/S = get_skill_datum(path) - // don't check, if we runtime let it happen. - return S.is_value_greater(existing, new_value) - /** * Skill datums */ + /datum/skill /// Our name var/name /// Our description var/desc - /// Our progression type + /// Color of the name as shown in the html readout + var/name_color = "#F0F0F0" // White on dark surface. + /// Our progression type. These are mostly used to skip typechecks overhead, don't go around messing with these. var/progression_type /// Abstract type var/abstract_type = /datum/skill + /// List of max levels. Only used in level skills, but present here for helper macros. + var/max_levels = INFINITY + /// skill threshold used in generic skill competency operations. + var/list/competency_thresholds + /// Base multiplier used in skill competency operations. + var/base_multiplier = 1 + /// Value added to the base multiplier depending on overall competency compared to maximum value/level. + var/competency_multiplier = 1 + /// A list of ways this skill can affect or be affected through actions and skill modifiers. + var/list/skill_traits = list(SKILL_SANITY, SKILL_INTELLIGENCE) /** * Ensures what someone's setting as a value for this skill is valid. @@ -41,6 +41,13 @@ GLOBAL_LIST_INIT(skill_datums, init_skill_datums()) /datum/skill/proc/sanitize_value(new_value) return new_value +/** + * Sets the new value of this skill in the holder skills list. + * As well as possible feedback messages or secondary effects on value change, that's on you. + */ +/datum/skill/proc/set_skill_value(datum/skill_holder/H, value, mob/owner) + H.skills[type] = value + /** * Checks if a value is greater */ @@ -52,7 +59,7 @@ GLOBAL_LIST_INIT(skill_datums, init_skill_datums()) /** * Standard value "render" */ -/datum/skill/proc/standard_render_value(value) +/datum/skill/proc/standard_render_value(value, level) return value // Just saying, the choice to use different sub-parent-types is to force coders to resolve issues as I won't be implementing custom procs to grab skill levels in a certain context. @@ -61,16 +68,18 @@ GLOBAL_LIST_INIT(skill_datums, init_skill_datums()) /datum/skill/binary abstract_type = /datum/skill/binary progression_type = SKILL_PROGRESSION_BINARY + competency_thresholds = list(THRESHOLD_COMPETENT = FALSE, THRESHOLD_EXPERT = TRUE, THRESHOLD_MASTER = TRUE) /datum/skill/binary/sanitize_value(new_value) return new_value? TRUE : FALSE -/datum/skill/binary/standard_render_value(value) +/datum/skill/binary/standard_render_value(value, level) return value? "Yes" : "No" /datum/skill/numerical abstract_type = /datum/skill/numerical progression_type = SKILL_PROGRESSION_NUMERICAL + competency_thresholds = list(THRESHOLD_COMPETENT = 25, THRESHOLD_EXPERT = 50, THRESHOLD_MASTER = 75) /// Max value of this skill var/max_value = 100 /// Min value of this skill @@ -81,7 +90,7 @@ GLOBAL_LIST_INIT(skill_datums, init_skill_datums()) /datum/skill/numerical/sanitize_value(new_value) return clamp(new_value, min_value, max_value) -/datum/skill/numerical/standard_render_value(value) +/datum/skill/numerical/standard_render_value(value, level) return display_as_percent? "[round(value/max_value/100, 0.01)]%" : "[value] / [max_value]" /datum/skill/enum @@ -93,3 +102,100 @@ GLOBAL_LIST_INIT(skill_datums, init_skill_datums()) /datum/skill/enum/sanitize_value(new_value) if(new_value in valid_values) return new_value + +/** + * Classing r p g styled skills, tiered by lvl, and current/nextlvl experience. + */ +/datum/skill/level + abstract_type = /datum/skill/level + progression_type = SKILL_PROGRESSION_LEVEL + max_levels = STD_MAX_LVL + var/standard_xp_lvl_up = STD_XP_LVL_UP //the standard required to level up. def: 100 + var/xp_lvl_multiplier = STD_XP_LVL_MULTI //standard required level up exp multiplier. def: 2 (100, 200, 400, 800 etc.) + var/level_up_method = STANDARD_LEVEL_UP //how levels are calculated. + var/list/levels = list() //level thresholds, if associative, these will be preceded by tiers such as "novice" or "trained" + var/associative = FALSE //See above. + var/unskilled_tier = "Unskilled" //Only relevant for associative experience levels + +//Builds the levels list. +/datum/skill/level/New() + . = ..() + var/max_assoc = "" + var/max_assoc_start = 1 + for(var/lvl in 1 to max_levels) + var/value + switch(level_up_method) + if(STANDARD_LEVEL_UP) + value = XP_LEVEL(standard_xp_lvl_up, xp_lvl_multiplier, lvl) + if(DWARFY_LEVEL_UP) + value = DORF_XP_LEVEL(standard_xp_lvl_up, xp_lvl_multiplier, lvl) + value = round(value, 1) + if(!associative) + levels += value + continue + if(max_assoc) + levels["[max_assoc] +[max_assoc_start++]"] = value + continue + var/key = LAZYACCESS(levels, lvl) + if(!key) + if(lvl == 1) //You dun goof it. + stack_trace("Skill datum [src] was set to have an associative levels list despite the latter having no key value.") + associative = FALSE + levels += value + continue + max_assoc = levels[lvl-1] + levels["[max_assoc] +[max_assoc_start++]"] = value + levels[key] = value + +/datum/skill/level/sanitize_value(new_value) + return max(new_value, 0) + +/datum/skill/level/set_skill_value(datum/skill_holder/H, value, datum/mind/M, silent = FALSE) + H.skills[type] = value + var/new_level + for(var/k in levels) + if(value < (associative ? levels[k] : k)) + break + new_level++ + var/old_level = LAZYACCESS(H.skill_levels, type) + LAZYSET(H.skill_levels, type, new_level) + . = new_level - old_level + if(silent || !(M?.current)) + return + if(. > 0) + to_chat(M.current, "I feel like I've become more proficient at [name]!") + else if(. < 0) + to_chat(M.current, "I feel like I've become worse at [name]!") + +/datum/skill/level/standard_render_value(value, level) + var/current_lvl = associative ? (!level ? unskilled_tier : levels[level]) : level + var/current_lvl_xp_sum = 0 + if(level) + current_lvl_xp_sum = associative ? levels[levels[level]] : levels[level] + var/next_index = min(max_levels, level+1) + var/next_lvl_xp = associative ? levels[levels[next_index]] : levels[next_index] + if(next_lvl_xp > current_lvl_xp_sum) + next_lvl_xp -= current_lvl_xp_sum + + return "[associative ? current_lvl : "Lvl. [current_lvl]"] ([value - current_lvl_xp_sum]/[next_lvl_xp])[level == max_levels ? " \[MAX!\]" : ""]" + +/datum/skill/level/job + abstract_type = /datum/skill/level/job + levels = list("Basic", "Trained", "Experienced", "Master") + competency_thresholds = list(THRESHOLD_COMPETENT = JOB_SKILL_TRAINED, THRESHOLD_EXPERT = JOB_SKILL_EXPERT, THRESHOLD_MASTER = JOB_SKILL_MASTER) + associative = TRUE + +//quite the reference, no? +/datum/skill/level/dwarfy + abstract_type = /datum/skill/level/dwarfy + standard_xp_lvl_up = DORF_XP_LVL_UP + xp_lvl_multiplier = DORF_XP_LVL_MULTI + max_levels = DORF_MAX_LVL + level_up_method = DWARFY_LEVEL_UP + levels = list("Novice", "Adequate", "Competent", "Skilled", + "Proficient", "Talented", "Adept", "Expert", + "Professional", "Accomplished", "Great", "Master", + "High Master", "Grand Master", "Legendary") + competency_thresholds = list(THRESHOLD_COMPETENT = DORF_SKILL_COMPETENT, THRESHOLD_EXPERT = DORF_SKILL_EXPERT, THRESHOLD_MASTER = DORF_SKILL_MASTER) + associative = TRUE + unskilled_tier = "Dabbling" diff --git a/code/datums/skills/_skill_holder.dm b/code/datums/skills/_skill_holder.dm index e16804ab7f..071db3306a 100644 --- a/code/datums/skills/_skill_holder.dm +++ b/code/datums/skills/_skill_holder.dm @@ -1,78 +1,200 @@ /** * Skill holder datums + * All procs are tied to the mind, since they are always expected to have a skill holder anyway. */ /datum/skill_holder /// Our list of skills and values. Lazylist. Associative. Keys are datum typepaths to the skill. var/list/skills /// Same as [skills] but affinities, which are multiplied to increase amount when gaining skills. var/list/skill_affinities + /// Let's say we want to get a specific skill "level" without looping through a proc everytime. + /// Only supported by skills with tiers or levels. + var/list/skill_levels + /// current skill modifiers lists, per value, affinity, level. + var/list/skill_value_mods + var/list/skill_affinity_mods + var/list/skill_level_mods + /// List of all current skill modifiers, so we don't add the same ones twice. + var/list/all_current_skill_modifiers + /// List of original values stored at the time a modifier with the MODIFIER_SKILL_ORIGIN_DIFF enabled was added. + var/list/original_values + var/list/original_affinities + var/list/original_levels /** * Grabs the value of a skill. */ -/datum/skill_holder/proc/get_skill_value(skill) +/datum/mind/proc/get_skill_value(skill, apply_modifiers = TRUE) if(!ispath(skill)) CRASH("Invalid get_skill_value call. Use typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this. - if(!skills) - return null - return LAZYACCESS(skills, skill) + if(!skill_holder.skills) + . = 0 + else + . = skill_holder.skills[skill] || 0 + if(apply_modifiers && skill_holder.skill_value_mods) + var/L = LAZYACCESS(skill_holder.skill_value_mods, skill) + for(var/k in L) + var/datum/skill_modifier/M = GLOB.skill_modifiers[k] + . = M.apply_modifier(., skill, skill_holder, MODIFIER_TARGET_VALUE) + +/** + * Grabs the level of a skill. Only supported by skills with tiers or levels. + */ +/datum/mind/proc/get_skill_level(skill, apply_modifiers = TRUE, round = FALSE) + if(!ispath(skill, /datum/skill)) + CRASH("Invalid get_skill_value call. Use skill typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this. + if(!skill_holder.skill_levels) + . = 0 + else + . = skill_holder.skill_levels[skill] || 0 + if(apply_modifiers && skill_holder.skill_level_mods) + var/L = LAZYACCESS(skill_holder.skill_level_mods, skill) + for(var/k in L) + var/datum/skill_modifier/M = GLOB.skill_modifiers[k] + . = M.apply_modifier(., skill, skill_holder, MODIFIER_TARGET_LEVEL) + . = SANITIZE_SKILL_LEVEL(skill, round ? round(., 1) : .) /** * Grabs our affinity for a skill. !!This is a multiplier!! */ -/datum/skill_holder/proc/get_skill_affinity(skill) - if(!ispath(skill)) - CRASH("Invalid get_skill_affinity call. Use typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this. - if(!skills) - return 1 - var/affinity = LAZYACCESS(skill_affinities, skill) - if(isnull(affinity)) - return 1 - return affinity +/datum/mind/proc/get_skill_affinity(skill, apply_modifiers = TRUE) + . = 1 + if(!ispath(skill, /datum/skill)) + CRASH("Invalid get_skill_affinity call. Use skill typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this. + var/affinity = LAZYACCESS(skill_holder.skill_affinities, skill) + if(!isnull(affinity)) + . = affinity + if(apply_modifiers && skill_holder.skill_affinity_mods) + var/L = LAZYACCESS(skill_holder.skill_affinity_mods, skill) + for(var/k in L) + var/datum/skill_modifier/M = GLOB.skill_modifiers[k] + . = M.apply_modifier(., skill, skill_holder, MODIFIER_TARGET_AFFINITY) + /** * Sets the value of a skill. */ -/datum/skill_holder/proc/set_skill_value(skill, value) - if(!ispath(skill)) - CRASH("Invalid set_skill_value call. Use typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this. - LAZYINITLIST(skills) - value = sanitize_skill_value(skill, value) +/datum/mind/proc/set_skill_value(skill, value, silent = FALSE) + if(!ispath(skill, /datum/skill)) + CRASH("Invalid set_skill_value call. Use skill typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this. + var/datum/skill/S = GLOB.skill_datums[skill] + value = S.sanitize_value(value) if(!isnull(value)) - LAZYSET(skills, skill, value) + LAZYINITLIST(skill_holder.skills) + S.set_skill_value(skill_holder, value, src, silent) return TRUE return FALSE /** * Boosts a skill to a value if not aobve */ -/datum/skill_holder/proc/boost_skill_value_to(skill, value) - var/current = get_skill_value(skill) - if(!is_skill_value_greater(skill, current, value)) +/datum/mind/proc/boost_skill_value_to(skill, value, silent = FALSE, current) + current = current || get_skill_value(skill, FALSE) + if(!IS_SKILL_VALUE_GREATER(skill, current, value)) return FALSE - set_skill_value(skill, value) + set_skill_value(skill, value, silent) return TRUE /** * Automatic skill increase, multiplied by skill affinity if existing. * Only works if skill is numerical. */ -/datum/skill_holder/proc/auto_gain_experience(skill, value) - if(!ispath(skill, /datum/skill/numerical)) - CRASH("You cannot auto increment a non numerical skill!") - var/current = get_skill_value(skill) +/datum/mind/proc/auto_gain_experience(skill, value, maximum, silent = FALSE) + if(!ispath(skill, /datum/skill)) + CRASH("Invalid set_skill_value call. Use skill typepaths.") + var/datum/skill/S = GLOB.skill_datums[skill] + if(S.progression_type != SKILL_PROGRESSION_NUMERICAL && S.progression_type != SKILL_PROGRESSION_LEVEL) + CRASH("You cannot auto increment a non numerical(experience skill!") + var/current = get_skill_value(skill, FALSE) var/affinity = get_skill_affinity(skill) - boost_skill_value_to(skill, current + (value * affinity)) + var/target_value = current + (value * affinity) + if(maximum) + target_value = min(target_value, maximum) + if(target_value == maximum) //no more experience to gain, early return. + return + boost_skill_value_to(skill, target_value, silent, current) + +/** + * Generic value modifier proc that uses one skill. + * Args: + * * value : the value to modify, may be a delay, damage, probability. + * * threshold : The difficulty of the action, in short. Refer to __DEFINES/skills/defines.dm for the defines. + * * modifier_is_multiplier : wheter the modifier is a multiplier or a divisor. + */ +/datum/mind/proc/action_skill_mod(skill, value, threshold, modifier_is_multiplier = TRUE) + var/datum/skill/S = GLOB.skill_datums[skill] + if(!S) + return value + var/mod = S.base_multiplier + switch(S.progression_type) + if(SKILL_PROGRESSION_LEVEL) + var/datum/skill/level/L = S + var/skill_lvl = get_skill_level(L.type) + mod += skill_lvl/(L.max_levels+max(L.competency_thresholds[threshold]-skill_lvl, 0))*L.competency_multiplier + if(SKILL_PROGRESSION_NUMERICAL) + var/datum/skill/numerical/N = S + var/skill_val = get_skill_value(N.type) + mod += skill_val/(N.max_value+max(N.competency_thresholds[threshold]-skill_val, 0))*N.competency_multiplier + else + var/comp_threshold = S.competency_thresholds[threshold] + mod += (comp_threshold ? (get_skill_value(S.type) / comp_threshold) : get_skill_value(S.type))*S.competency_multiplier + . = modifier_is_multiplier ? value*mod : value/mod + +/** + * Generic value modifier proc that uses several skills, intended for items. + * Args: + * * item/I : the item used in this action. its used_skills list variable contains the skills exercised with it. + * * value : the value to modify, may be a delay, damage, probability. + * * traits : the required traits each skill (either in I.used_skills or the skill datum skill_traits) must have to influence + * * the value. + * * bad_traits : the opposite of the above. + * * modifier_is_multiplier : wheter the modifier is a multiplier or a divisor. + */ +/datum/mind/proc/item_action_skills_mod(obj/item/I, value, traits, bad_traits, modifier_is_multiplier = TRUE) + . = value + var/sum = 0 + var/divisor = 0 + var/one_trait = istext(traits) + var/one_bad_trait = istext(bad_traits) + for(var/k in I.used_skills) + var/datum/skill/S = GLOB.skill_datums[k] + if(!S) + continue + var/our_traits = S.skill_traits + our_traits |= I.used_skills[k] + if(traits && !(one_trait ? (traits in our_traits) : length(our_traits & traits))) + continue + if(bad_traits && (one_bad_trait ? (bad_traits in our_traits) : length(our_traits & bad_traits))) + continue + var/mod = S.base_multiplier + switch(S.progression_type) + if(SKILL_PROGRESSION_LEVEL) + var/datum/skill/level/L = S + var/skill_lvl = get_skill_level(L.type) + mod += skill_lvl/(L.max_levels+max(L.competency_thresholds[I.skill_difficulty]-skill_lvl, 0))*L.competency_multiplier + if(SKILL_PROGRESSION_NUMERICAL) + var/datum/skill/numerical/N = S + var/skill_val = get_skill_value(N.type) + mod += skill_val/(N.max_value+max(N.competency_thresholds[I.skill_difficulty]-skill_val, 0))*N.competency_multiplier + else + var/comp_threshold = S.competency_thresholds[I.skill_difficulty] + mod += (comp_threshold ? (get_skill_value(S.type) / comp_threshold) : get_skill_value(S.type))*S.competency_multiplier + sum += mod + divisor++ + if(divisor) + . = modifier_is_multiplier ? value*(sum/divisor) : value/(sum/divisor) /** * Generates a HTML readout of our skills. * Port to tgui-next when? */ -/datum/skill_holder/proc/html_readout() +/datum/mind/proc/skill_html_readout() var/list/out = list("

Skills


") out += "" - for(var/path in skills) + for(var/path in skill_holder.skills|skill_holder.skill_value_mods|skill_holder.skill_level_mods) var/datum/skill/S = GLOB.skill_datums[path] - out += "" + var/skill_value = get_skill_value(path) + var/skill_level = get_skill_level(path, round = TRUE) + out += "" out += "
SkillValue
[S.name][S.standard_render_value(skills[path])]
[S.name][S.standard_render_value(skill_value, skill_level)]
" return out.Join("") diff --git a/code/datums/skills/_skill_modifier.dm b/code/datums/skills/_skill_modifier.dm new file mode 100644 index 0000000000..a28cf3aebd --- /dev/null +++ b/code/datums/skills/_skill_modifier.dm @@ -0,0 +1,204 @@ +GLOBAL_LIST_EMPTY_TYPED(skill_modifiers, /datum/skill_modifier) +GLOBAL_LIST_EMPTY(potential_skills_per_mod) +GLOBAL_LIST_EMPTY(potential_mods_per_skill) + +/** + * Base skill modifier datum, used to modify a player skills without directly touching their values, levels and affinity + * and cause lots of edge cases. These are fairly simple overall... make a subtype though, don't use this one. + */ +/datum/skill_modifier + /// flags for this skill modifier. + var/modifier_flags = NONE + /// target skills, can be a specific skill typepath or a list of skill traits. + var/target_skills = /datum/skill + /// the GLOB.potential_skills_per_mod key generated on runtime. You shouldn't be var-editing it. + var/target_skills_key + /// The identifier key this skill modifier is associated with. + var/identifier + /// skill affinity modifier, can be a multiplier or addendum, depending on the modifier_flags. + var/affinity_mod = 1 + /// skill value modifier, see above. + var/value_mod = 1 + /// skill level modifier, see above. + var/level_mod = 1 + /// Priority of this skill modifier compared to other ones. + var/priority = MODIFIER_SKILL_PRIORITY_DEF + +/datum/skill_modifier/New(id, register = FALSE) + identifier = GET_SKILL_MOD_ID(type, id) + if(id) + var/former_id = identifier + var/dupe = 0 + while(GLOB.skill_modifiers[identifier]) + identifier = "[former_id][++dupe]" + + if(register) + register() + +/datum/skill_modifier/proc/register() + if(GLOB.skill_modifiers[identifier]) + CRASH("Skill modifier identifier \"[identifier]\" already taken.") + GLOB.skill_modifiers[identifier] = src + if(ispath(target_skills)) + target_skills_key = target_skills + var/list/mod_L = GLOB.potential_mods_per_skill[target_skills] + if(!mod_L) + mod_L = GLOB.potential_mods_per_skill[target_skills] = list() + else + BINARY_INSERT(identifier, mod_L, datum/skill_modifier, src, priority, COMPARE_VALUE) + mod_L[identifier] = src + GLOB.potential_skills_per_mod[target_skills_key] = list(target_skills) + else //Should be a list. + var/list/T = target_skills + T = sortTim(target_skills, /proc/cmp_text_asc) //Sort the list contents alphabetically. + target_skills_key = T.Join("-") + var/list/L = GLOB.potential_skills_per_mod[target_skills_key] + if(!L) + L = list() + for(var/path in GLOB.skill_datums) + if(GLOB.skill_datums[path].skill_traits & target_skills) + L += path + GLOB.potential_skills_per_mod[target_skills_key] = L + for(var/path in L) + var/list/mod_L = GLOB.potential_mods_per_skill[path] + if(!mod_L) + mod_L = GLOB.potential_mods_per_skill[path] = list() + else + BINARY_INSERT(identifier, mod_L, datum/skill_modifier, src, priority, COMPARE_VALUE) + mod_L[identifier] = src + +/datum/skill_modifier/Destroy() + for(var/path in GLOB.potential_skills_per_mod[target_skills_key]) + var/mod_L = GLOB.potential_mods_per_skill[path] + mod_L -= identifier + if(!length(mod_L)) + GLOB.potential_mods_per_skill -= path + GLOB.skill_modifiers -= identifier + return ..() + +#define ADD_MOD_STEP(L, P, O, G) \ + var/__L = L[P];\ + if(!__L){\ + L[P] = list(id)\ + } else {\ + L[P] = GLOB.potential_mods_per_skill[P] & (__L + id)\ + }\ + if(M.modifier_flags & MODIFIER_SKILL_ORIGIN_DIFF){\ + LAZYADDASSOC(O, id, "[P]" = G)\ + } + +/datum/mind/proc/add_skill_modifier(id) + if(LAZYACCESS(skill_holder.all_current_skill_modifiers, id)) + return + var/datum/skill_modifier/M = GLOB.skill_modifiers[id] + if(!M) + CRASH("Invalid add_skill_modifier id: [id].") + if(M.modifier_flags & MODIFIER_SKILL_BODYBOUND && !current) + CRASH("Body-bound skill modifier [M] was tried to be added to a mob-less mind.") + + if(M.modifier_flags & MODIFIER_SKILL_VALUE) + LAZYINITLIST(skill_holder.skill_value_mods) + if(M.modifier_flags & MODIFIER_SKILL_AFFINITY) + LAZYINITLIST(skill_holder.skill_affinity_mods) + if(M.modifier_flags & MODIFIER_SKILL_LEVEL) + LAZYINITLIST(skill_holder.skill_level_mods) + for(var/path in GLOB.potential_skills_per_mod[M.target_skills_key]) + if(M.modifier_flags & MODIFIER_SKILL_VALUE) + ADD_MOD_STEP(skill_holder.skill_value_mods, path, skill_holder.original_values, get_skill_value(path, FALSE)) + if(M.modifier_flags & MODIFIER_SKILL_AFFINITY) + ADD_MOD_STEP(skill_holder.skill_affinity_mods, path, skill_holder.original_affinities, get_skill_affinity(path, FALSE)) + if(M.modifier_flags & MODIFIER_SKILL_LEVEL) + ADD_MOD_STEP(skill_holder.skill_level_mods, path, skill_holder.original_levels, get_skill_level(path, FALSE)) + LAZYSET(skill_holder.all_current_skill_modifiers, id, TRUE) + + if(M.modifier_flags & MODIFIER_SKILL_BODYBOUND) + M.RegisterSignal(src, COMSIG_MIND_TRANSFER, /datum/skill_modifier.proc/on_mind_transfer) + M.RegisterSignal(current, COMSIG_MOB_ON_NEW_MIND, /datum/skill_modifier.proc/on_mob_new_mind, TRUE) + RegisterSignal(M, COMSIG_PARENT_PREQDELETED, .proc/on_skill_modifier_deletion) + +#undef ADD_MOD_STEP + +#define REMOVE_MOD_STEP(L, P, O)\ + LAZYREMOVEASSOC(L, P, id);\ + if(M.modifier_flags & MODIFIER_SKILL_ORIGIN_DIFF){\ + LAZYREMOVEASSOC(O, id, "[P]")\ + } + +/datum/mind/proc/remove_skill_modifier(id, mind_transfer = FALSE) + if(!LAZYACCESS(skill_holder.all_current_skill_modifiers, id)) + return + var/datum/skill_modifier/M = GLOB.skill_modifiers[id] + if(!M) + CRASH("Invalid remove_skill_modifier id: [id].") + + if(!skill_holder.skill_value_mods && !skill_holder.skill_affinity_mods && !skill_holder.skill_level_mods) + return + for(var/path in GLOB.potential_skills_per_mod[M.target_skills_key]) + if(M.modifier_flags & MODIFIER_SKILL_VALUE && skill_holder.skill_value_mods) + REMOVE_MOD_STEP(skill_holder.skill_value_mods, path, skill_holder.original_values) + if(M.modifier_flags & MODIFIER_SKILL_AFFINITY && skill_holder.skill_affinity_mods) + REMOVE_MOD_STEP(skill_holder.skill_affinity_mods, path, skill_holder.original_affinities) + if(M.modifier_flags & MODIFIER_SKILL_LEVEL && skill_holder.skill_level_mods) + REMOVE_MOD_STEP(skill_holder.skill_level_mods, path, skill_holder.original_levels) + LAZYREMOVE(skill_holder.all_current_skill_modifiers, id) + + if(!mind_transfer && M.modifier_flags & MODIFIER_SKILL_BODYBOUND) + M.UnregisterSignal(src, COMSIG_MIND_TRANSFER) + M.UnregisterSignal(current, list(COMSIG_MOB_ON_NEW_MIND)) + UnregisterSignal(M, COMSIG_PARENT_PREQDELETED) + +#undef REMOVE_MOD_STEP + +/datum/mind/proc/on_skill_modifier_deletion(datum/skill_modifier/source) + remove_skill_modifier(source.identifier) + +/datum/skill_modifier/proc/apply_modifier(value, skillpath, datum/skill_holder/H, method = MODIFIER_TARGET_VALUE) + . = value + var/mod = value_mod + switch(method) + if(MODIFIER_TARGET_LEVEL) + mod = level_mod + if(MODIFIER_TARGET_AFFINITY) + mod = affinity_mod + + if(modifier_flags & MODIFIER_USE_THRESHOLDS && istext(mod)) + var/datum/skill/S = GLOB.skill_datums[skillpath] + if(method == MODIFIER_TARGET_VALUE && S.progression_type == SKILL_PROGRESSION_LEVEL) + var/datum/skill/level/L = S + switch(L.level_up_method) + if(STANDARD_LEVEL_UP) + mod = XP_LEVEL(L.standard_xp_lvl_up, L.xp_lvl_multiplier, S.competency_thresholds[mod]) + if(DWARFY_LEVEL_UP) + mod = DORF_XP_LEVEL(L.standard_xp_lvl_up, L.xp_lvl_multiplier, S.competency_thresholds[mod]) + else + mod = S.competency_thresholds[mod] + + var/diff = 0 + if(modifier_flags & (MODIFIER_SKILL_VIRTUE|MODIFIER_SKILL_HANDICAP)) + if(modifier_flags & MODIFIER_SKILL_VIRTUE) + . = max(., mod) + if(modifier_flags & MODIFIER_SKILL_HANDICAP) + . = min(., mod) + diff = . - mod + else if(modifier_flags & MODIFIER_SKILL_MULT) + . *= mod + else + . += mod + + if(modifier_flags & MODIFIER_SKILL_ORIGIN_DIFF) + var/list/to_access = H.original_values + switch(method) + if(MODIFIER_TARGET_LEVEL) + to_access = H.original_levels + if(MODIFIER_TARGET_AFFINITY) + to_access = H.original_affinities + . += value - diff - LAZYACCESS(to_access[identifier], "[skillpath]") + +///Body bound modifier signal procs. +/datum/skill_modifier/proc/on_mind_transfer(datum/mind/source, mob/new_character, mob/old_character) + source.remove_skill_modifier(identifier, TRUE) + UnregisterSignal(source, COMSIG_MIND_TRANSFER) + +/datum/skill_modifier/proc/on_mob_new_mind(mob/source) + source.mind.add_skill_modifier(identifier) + RegisterSignal(source.mind, COMSIG_MIND_TRANSFER, /datum/skill_modifier.proc/on_mind_transfer) diff --git a/code/datums/skills/engineering.dm b/code/datums/skills/engineering.dm new file mode 100644 index 0000000000..db7b33450c --- /dev/null +++ b/code/datums/skills/engineering.dm @@ -0,0 +1,5 @@ +/datum/skill/level/job/wiring + name = "Wiring" + desc = "How proficient and knowledged you are at wiring beyond laying cables on the floor." + name_color = COLOR_PALE_ORANGE + skill_traits = list(SKILL_SANITY, SKILL_INTELLIGENCE, SKILL_USE_TOOL, SKILL_TRAINING_TOOL) diff --git a/code/datums/skills/medical.dm b/code/datums/skills/medical.dm index 3b67cacb04..404c141157 100644 --- a/code/datums/skills/medical.dm +++ b/code/datums/skills/medical.dm @@ -1,3 +1,5 @@ /datum/skill/numerical/surgery name = "Surgery" desc = "How proficient you are at doing surgery." + name_color = COLOR_PALE_BLUE_GRAY + competency_multiplier = 1.5 // 60% surgery speed up at max value of 100, considering the base multiplier. diff --git a/code/datums/skills/modifiers/job.dm b/code/datums/skills/modifiers/job.dm new file mode 100644 index 0000000000..7d79ae89b3 --- /dev/null +++ b/code/datums/skills/modifiers/job.dm @@ -0,0 +1,35 @@ +/// Jobbie skill modifiers. + +/datum/skill_modifier/job + modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_VIRTUE|MODIFIER_SKILL_ORIGIN_DIFF + priority = MODIFIER_SKILL_PRIORITY_MAX + +/datum/skill_modifier/job/surgery + target_skills = /datum/skill/numerical/surgery + value_mod = STARTING_SKILL_SURGERY_MEDICAL + +/datum/skill_modifier/job/affinity + modifier_flags = MODIFIER_SKILL_AFFINITY|MODIFIER_SKILL_VIRTUE + affinity_mod = STARTING_SKILL_AFFINITY_DEF_JOB + +/datum/skill_modifier/job/affinity/surgery + target_skills = /datum/skill/numerical/surgery + +/datum/skill_modifier/job/affinity/wiring + target_skills = /datum/skill/level/job/wiring + +/// Level skill modifiers below. +/datum/skill_modifier/job/level + modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_LEVEL|MODIFIER_SKILL_VIRTUE|MODIFIER_SKILL_ORIGIN_DIFF + level_mod = JOB_SKILL_TRAINED + +/datum/skill_modifier/job/level/New(id) + if(level_mod) + value_mod = GET_STANDARD_LVL(level_mod) + ..() + +/datum/skill_modifier/job/level/wiring + target_skills = /datum/skill/level/job/wiring + +/datum/skill_modifier/job/level/wiring/basic + level_mod = JOB_SKILL_BASIC diff --git a/code/datums/skills/modifiers/mood.dm b/code/datums/skills/modifiers/mood.dm new file mode 100644 index 0000000000..30f24afcc4 --- /dev/null +++ b/code/datums/skills/modifiers/mood.dm @@ -0,0 +1,8 @@ +/datum/skill_modifier/bad_mood + modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_LEVEL|MODIFIER_SKILL_MULT|MODIFIER_SKILL_BODYBOUND + target_skills = list(SKILL_SANITY) + +/datum/skill_modifier/great_mood + modifier_flags = MODIFIER_SKILL_AFFINITY|MODIFIER_SKILL_MULT|MODIFIER_SKILL_BODYBOUND + target_skills = list(SKILL_SANITY) + affinity_mod = 1.2 diff --git a/code/datums/skills/modifiers/organs.dm b/code/datums/skills/modifiers/organs.dm new file mode 100644 index 0000000000..13ebaf0658 --- /dev/null +++ b/code/datums/skills/modifiers/organs.dm @@ -0,0 +1,13 @@ +/datum/skill_modifier/brain_damage + target_skills = list(SKILL_INTELLIGENCE) + modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_AFFINITY|MODIFIER_SKILL_LEVEL|MODIFIER_SKILL_MULT|MODIFIER_SKILL_BODYBOUND + value_mod = 0.85 + level_mod = 0.85 + affinity_mod = 0.85 + +/datum/skill_modifier/heavy_brain_damage + target_skills = list(SKILL_INTELLIGENCE) + modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_AFFINITY|MODIFIER_SKILL_LEVEL|MODIFIER_SKILL_BODYBOUND|MODIFIER_SKILL_HANDICAP|MODIFIER_USE_THRESHOLDS + priority = MODIFIER_SKILL_PRIORITY_LOW + value_mod = THRESHOLD_COMPETENT + level_mod = THRESHOLD_COMPETENT diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 4c200f110d..b976ac0fc8 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -120,11 +120,13 @@ /datum/status_effect/mesmerize/on_creation(mob/living/new_owner, set_duration) . = ..() ADD_TRAIT(owner, TRAIT_MUTE, "mesmerize") + ADD_TRAIT(owner, TRAIT_COMBAT_MODE_LOCKED, "mesmerize") owner.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/mesmerize) /datum/status_effect/mesmerize/on_remove() . = ..() REMOVE_TRAIT(owner, TRAIT_MUTE, "mesmerize") + REMOVE_TRAIT(owner, TRAIT_COMBAT_MODE_LOCKED, "mesmerize") owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/mesmerize) /datum/status_effect/mesmerize/on_creation(mob/living/new_owner, set_duration) diff --git a/code/datums/tgs_event_handler.dm b/code/datums/tgs_event_handler.dm new file mode 100644 index 0000000000..a3324121bf --- /dev/null +++ b/code/datums/tgs_event_handler.dm @@ -0,0 +1,20 @@ +/datum/tgs_event_handler/impl/HandleEvent(event_code, ...) + switch(event_code) + if(TGS_EVENT_REBOOT_MODE_CHANGE) + var/list/reboot_mode_lookup = list ("[TGS_REBOOT_MODE_NORMAL]" = "be normal", "[TGS_REBOOT_MODE_SHUTDOWN]" = "shutdown the server", "[TGS_REBOOT_MODE_RESTART]" = "hard restart the server") + var old_reboot_mode = args[2] + var new_reboot_mode = args[3] + message_admins("TGS: Reboot will no longer [reboot_mode_lookup["[old_reboot_mode]"]], it will instead [reboot_mode_lookup["[new_reboot_mode]"]]") + if(TGS_EVENT_PORT_SWAP) + message_admins("TGS: Changing port from [world.port] to [args[2]]") + if(TGS_EVENT_INSTANCE_RENAMED) + message_admins("TGS: Instance renamed to from [world.TgsInstanceName()] to [args[2]]") + if(TGS_EVENT_COMPILE_START) + message_admins("TGS: Deployment started, new game version incoming...") + if(TGS_EVENT_COMPILE_CANCELLED) + message_admins("TGS: Deployment cancelled!") + if(TGS_EVENT_COMPILE_FAILURE) + message_admins("TGS: Deployment failed!") + if(TGS_EVENT_DEPLOYMENT_COMPLETE) + message_admins("TGS: Deployment complete!") + to_chat(world, "Server updated, changes will be applied on the next round...") diff --git a/code/datums/wires/_wires.dm b/code/datums/wires/_wires.dm index ad24126e45..a96e14d4d7 100644 --- a/code/datums/wires/_wires.dm +++ b/code/datums/wires/_wires.dm @@ -33,6 +33,9 @@ var/list/assemblies = list() // List of attached assemblies. var/randomize = 0 // If every instance of these wires should be random. // Prevents wires from showing up in station blueprints + var/req_knowledge = INFINITY //wiring skill level on which the functions are revealed. + var/req_skill = JOB_SKILL_BASIC //used in user's cutting/pulsing/mending speed calculations. + var/list/current_users //list of untrained people currently interacting with this set of wires. /datum/wires/New(atom/holder) ..() @@ -130,8 +133,22 @@ cut_wires += wire on_cut(wire, mend = FALSE) -/datum/wires/proc/cut_color(color) +/datum/wires/proc/cut_color(color, mob/living/user) + LAZYINITLIST(current_users) + if(current_users[user]) + return FALSE + if(req_skill && user?.mind) + var/level_diff = req_skill - user.mind.get_skill_level(/datum/skill/level/job/wiring, round = TRUE) + if(level_diff > 0) + LAZYSET(current_users, user, TRUE) + to_chat(user, "You begin cutting [holder]'s [color] wire...") + if(!do_after(user, 0.75 SECONDS * level_diff, target = holder) || !interactable(user)) + LAZYREMOVE(current_users, user) + return FALSE + LAZYREMOVE(current_users, user) + to_chat(user, "You cut [holder]'s [color] wire.") cut(get_wire(color)) + return TRUE /datum/wires/proc/cut_random() cut(wires[rand(1, wires.len)]) @@ -146,7 +163,21 @@ on_pulse(wire, user) /datum/wires/proc/pulse_color(color, mob/living/user) + LAZYINITLIST(current_users) + if(current_users[user]) + return FALSE + if(req_skill && user?.mind) + var/level_diff = req_skill - user.mind.get_skill_level(/datum/skill/level/job/wiring, round = TRUE) + if(level_diff > 0) + LAZYSET(current_users, user, TRUE) + to_chat(user, "You begin pulsing [holder]'s [color] wire...") + if(!do_after(user, 1.5 SECONDS * level_diff, target = holder) || !interactable(user)) + LAZYREMOVE(current_users, user) + return FALSE + LAZYREMOVE(current_users, user) + to_chat(user, "You pulse [holder]'s [color] wire.") pulse(get_wire(color), user) + return TRUE /datum/wires/proc/pulse_assembly(obj/item/assembly/S) for(var/color in assemblies) @@ -224,7 +255,7 @@ var/reveal_wires = FALSE // Admin ghost can see a purpose of each wire. - if(IsAdminGhost(user)) + if(IsAdminGhost(user) || user.mind.get_skill_level(/datum/skill/level/job/wiring) >= req_knowledge) reveal_wires = TRUE // Same for anyone with an abductor multitool. @@ -259,18 +290,16 @@ if("cut") I = L.is_holding_tool_quality(TOOL_WIRECUTTER) if(I || IsAdminGhost(usr)) - if(I && holder) + if(cut_color(target_wire, L) && I && holder) I.play_tool_sound(holder, 20) - cut_color(target_wire) . = TRUE else to_chat(L, "You need wirecutters!") if("pulse") I = L.is_holding_tool_quality(TOOL_MULTITOOL) if(I || IsAdminGhost(usr)) - if(I && holder) + if(pulse_color(target_wire, L) && I && holder) I.play_tool_sound(holder, 20) - pulse_color(target_wire, L) . = TRUE else to_chat(L, "You need a multitool!") diff --git a/code/datums/wires/airalarm.dm b/code/datums/wires/airalarm.dm index 0c4715e27e..dae92d3c42 100644 --- a/code/datums/wires/airalarm.dm +++ b/code/datums/wires/airalarm.dm @@ -1,6 +1,7 @@ /datum/wires/airalarm holder_type = /obj/machinery/airalarm proper_name = "Air Alarm" + req_knowledge = JOB_SKILL_MASTER /datum/wires/airalarm/New(atom/holder) wires = list( diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index b6699540c3..2b13344cc6 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -1,6 +1,7 @@ /datum/wires/airlock holder_type = /obj/machinery/door/airlock proper_name = "Generic Airlock" + req_skill = JOB_SKILL_UNTRAINED //Training wheel, as per request. var/wiretype /datum/wires/airlock/secure @@ -52,10 +53,11 @@ /datum/wires/airlock/interactable(mob/user) var/obj/machinery/door/airlock/A = holder + if(!A.panel_open) + return FALSE if(!A.hasSiliconAccessInArea(user) && A.isElectrified() && A.shock(user, 100)) return FALSE - if(A.panel_open) - return TRUE + return TRUE /datum/wires/airlock/get_status() var/obj/machinery/door/airlock/A = holder diff --git a/code/datums/wires/apc.dm b/code/datums/wires/apc.dm index dc126f612e..997c77aa51 100644 --- a/code/datums/wires/apc.dm +++ b/code/datums/wires/apc.dm @@ -1,6 +1,7 @@ /datum/wires/apc holder_type = /obj/machinery/power/apc proper_name = "APC" + req_knowledge = JOB_SKILL_MASTER /datum/wires/apc/New(atom/holder) wires = list( diff --git a/code/datums/wires/autolathe.dm b/code/datums/wires/autolathe.dm index f83bab5910..01e87228d4 100644 --- a/code/datums/wires/autolathe.dm +++ b/code/datums/wires/autolathe.dm @@ -1,6 +1,7 @@ /datum/wires/autolathe holder_type = /obj/machinery/autolathe proper_name = "Autolathe" + req_knowledge = JOB_SKILL_EXPERT /datum/wires/autolathe/New(atom/holder) wires = list( diff --git a/code/datums/wires/emitter.dm b/code/datums/wires/emitter.dm index d0e1352c0e..6d82a7db5a 100644 --- a/code/datums/wires/emitter.dm +++ b/code/datums/wires/emitter.dm @@ -1,6 +1,8 @@ /datum/wires/emitter holder_type = /obj/machinery/power/emitter + req_knowledge = JOB_SKILL_TRAINED + req_skill = JOB_SKILL_UNTRAINED /datum/wires/emitter/New(atom/holder) wires = list(WIRE_ZAP,WIRE_HACK) diff --git a/code/datums/wires/explosive.dm b/code/datums/wires/explosive.dm index 3d1ed8b746..dc4db9e85d 100644 --- a/code/datums/wires/explosive.dm +++ b/code/datums/wires/explosive.dm @@ -15,6 +15,7 @@ /datum/wires/explosive/c4 holder_type = /obj/item/grenade/plastic/c4 randomize = TRUE //Same behaviour since no wire actually disarms it + req_skill = JOB_SKILL_UNTRAINED /datum/wires/explosive/c4/interactable(mob/user) var/obj/item/grenade/plastic/c4/P = holder @@ -29,6 +30,7 @@ /datum/wires/explosive/pizza holder_type = /obj/item/pizzabox randomize = TRUE + req_skill = JOB_SKILL_MASTER /datum/wires/explosive/pizza/New(atom/holder) wires = list( diff --git a/code/datums/wires/microwave.dm b/code/datums/wires/microwave.dm index 8c74abfa46..c6e6aa13b5 100644 --- a/code/datums/wires/microwave.dm +++ b/code/datums/wires/microwave.dm @@ -1,6 +1,8 @@ /datum/wires/microwave holder_type = /obj/machinery/microwave proper_name = "Microwave" + req_knowledge = JOB_SKILL_TRAINED + req_skill = JOB_SKILL_UNTRAINED /datum/wires/microwave/New(atom/holder) wires = list( diff --git a/code/datums/wires/mulebot.dm b/code/datums/wires/mulebot.dm index a452b46830..988487727b 100644 --- a/code/datums/wires/mulebot.dm +++ b/code/datums/wires/mulebot.dm @@ -1,6 +1,7 @@ /datum/wires/mulebot holder_type = /mob/living/simple_animal/bot/mulebot randomize = TRUE + req_knowledge = JOB_SKILL_MASTER /datum/wires/mulebot/New(atom/holder) wires = list( diff --git a/code/datums/wires/particle_accelerator.dm b/code/datums/wires/particle_accelerator.dm index af89f0d6f1..b782e589dd 100644 --- a/code/datums/wires/particle_accelerator.dm +++ b/code/datums/wires/particle_accelerator.dm @@ -1,6 +1,8 @@ /datum/wires/particle_accelerator/control_box holder_type = /obj/machinery/particle_accelerator/control_box proper_name = "Particle Accelerator" + req_knowledge = JOB_SKILL_EXPERT + req_skill = JOB_SKILL_TRAINED /datum/wires/particle_accelerator/control_box/New(atom/holder) wires = list( diff --git a/code/datums/wires/r_n_d.dm b/code/datums/wires/r_n_d.dm index ea61c1779e..25d3b73fe0 100644 --- a/code/datums/wires/r_n_d.dm +++ b/code/datums/wires/r_n_d.dm @@ -1,6 +1,7 @@ /datum/wires/rnd holder_type = /obj/machinery/rnd randomize = TRUE + req_knowledge = JOB_SKILL_EXPERT /datum/wires/rnd/New(atom/holder) wires = list( diff --git a/code/datums/wires/radio.dm b/code/datums/wires/radio.dm index a1118da6d7..5db6ddd186 100644 --- a/code/datums/wires/radio.dm +++ b/code/datums/wires/radio.dm @@ -1,6 +1,8 @@ /datum/wires/radio holder_type = /obj/item/radio proper_name = "Radio" + req_knowledge = JOB_SKILL_TRAINED + req_skill = JOB_SKILL_UNTRAINED /datum/wires/radio/New(atom/holder) wires = list( diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm index aa7c3cc4c3..6ede0415da 100644 --- a/code/datums/wires/robot.dm +++ b/code/datums/wires/robot.dm @@ -1,6 +1,8 @@ /datum/wires/robot holder_type = /mob/living/silicon/robot randomize = TRUE + req_knowledge = JOB_SKILL_MASTER + req_skill = JOB_SKILL_TRAINED /datum/wires/robot/New(atom/holder) wires = list( diff --git a/code/datums/wires/suit_storage_unit.dm b/code/datums/wires/suit_storage_unit.dm index eb7781203b..4387d0dc76 100644 --- a/code/datums/wires/suit_storage_unit.dm +++ b/code/datums/wires/suit_storage_unit.dm @@ -1,6 +1,8 @@ /datum/wires/suit_storage_unit holder_type = /obj/machinery/suit_storage_unit proper_name = "Suit Storage Unit" + req_knowledge = JOB_SKILL_TRAINED + req_skill = JOB_SKILL_UNTRAINED /datum/wires/suit_storage_unit/New(atom/holder) wires = list( diff --git a/code/datums/wires/syndicatebomb.dm b/code/datums/wires/syndicatebomb.dm index 53c1a1b9bc..8e1cf5002f 100644 --- a/code/datums/wires/syndicatebomb.dm +++ b/code/datums/wires/syndicatebomb.dm @@ -1,6 +1,8 @@ /datum/wires/syndicatebomb holder_type = /obj/machinery/syndicatebomb randomize = TRUE + req_skill = JOB_SKILL_EXPERT //good luck, wannabe hero. + /datum/wires/syndicatebomb/New(atom/holder) wires = list( diff --git a/code/datums/wires/tesla_coil.dm b/code/datums/wires/tesla_coil.dm index fa858a9a8f..68fe8e72fc 100644 --- a/code/datums/wires/tesla_coil.dm +++ b/code/datums/wires/tesla_coil.dm @@ -2,6 +2,7 @@ /datum/wires/tesla_coil randomize = 1 //Only one wire don't need blueprints holder_type = /obj/machinery/power/tesla_coil + req_knowledge = JOB_SKILL_TRAINED /datum/wires/tesla_coil/New(atom/holder) wires = list(WIRE_ZAP) diff --git a/code/datums/wires/vending.dm b/code/datums/wires/vending.dm index 114791e873..6c7e59c24c 100644 --- a/code/datums/wires/vending.dm +++ b/code/datums/wires/vending.dm @@ -1,6 +1,7 @@ /datum/wires/vending holder_type = /obj/machinery/vending proper_name = "Vending Unit" + req_knowledge = JOB_SKILL_EXPERT /datum/wires/vending/New(atom/holder) wires = list( diff --git a/code/game/area/areas/ruins/space.dm b/code/game/area/areas/ruins/space.dm index 59c195ded1..a9f48af64e 100644 --- a/code/game/area/areas/ruins/space.dm +++ b/code/game/area/areas/ruins/space.dm @@ -129,7 +129,26 @@ icon_state = "crew_quarters" +//Ruin of Space Diner +/area/ruin/space/diner + name = "Space Diner" + +/area/ruin/space/diner/interior + name = "Space Diner" + icon_state = "maintbar" + has_gravity = STANDARD_GRAVITY + blob_allowed = FALSE //Nope, no winning in the diner as a blob. Gotta eat the main station. + +/area/ruin/space/diner/solars + requires_power = FALSE + dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT + valid_territory = FALSE + blob_allowed = FALSE + flags_1 = NONE + ambientsounds = ENGINEERING + name = "Space Diner Solar Array" + icon_state = "yellow" //Ruin of Derelict Oupost diff --git a/code/game/atoms.dm b/code/game/atoms.dm index dbb6864028..1ff27bafa9 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -32,6 +32,9 @@ var/list/filter_data //For handling persistent filters + var/custom_price + var/custom_premium_price + var/datum/component/orbiter/orbiters var/rad_flags = NONE // Will move to flags_1 when i can be arsed to @@ -578,6 +581,14 @@ SEND_SIGNAL(src, COMSIG_ATOM_RCD_ACT, user, the_rcd, passed_mode) return FALSE +/** + * Respond to a electric bolt action on our item + * + * Default behaviour is to return, we define here to allow for cleaner code later on + */ +/atom/proc/zap_act(power, zap_flags, shocked_targets) + return + /atom/proc/storage_contents_dump_act(obj/item/storage/src_object, mob/user) if(GetComponent(/datum/component/storage)) return component_storage_contents_dump_act(src_object, user) @@ -924,14 +935,14 @@ Proc for attack log creation, because really why not target.log_message(reverse_message, LOG_ATTACK, color="orange", log_globally=FALSE) // Filter stuff -/atom/movable/proc/add_filter(name,priority,list/params) +/atom/proc/add_filter(name,priority,list/params) LAZYINITLIST(filter_data) var/list/p = params.Copy() p["priority"] = priority filter_data[name] = p update_filters() -/atom/movable/proc/update_filters() +/atom/proc/update_filters() filters = null filter_data = sortTim(filter_data, /proc/cmp_filter_data_priority, TRUE) for(var/f in filter_data) @@ -940,11 +951,11 @@ Proc for attack log creation, because really why not arguments -= "priority" filters += filter(arglist(arguments)) -/atom/movable/proc/get_filter(name) +/atom/proc/get_filter(name) if(filter_data && filter_data[name]) return filters[filter_data.Find(name)] -/atom/movable/proc/remove_filter(name) +/atom/proc/remove_filter(name) if(filter_data && filter_data[name]) filter_data -= name update_filters() diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 32dde45195..9736f473e8 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -11,7 +11,7 @@ var/throw_range = 7 var/mob/pulledby = null var/initial_language_holder = /datum/language_holder - var/datum/language_holder/language_holder + var/datum/language_holder/language_holder // Mindless mobs and objects need language too, some times. Mind holder takes prescedence. var/verb_say = "says" var/verb_ask = "asks" var/verb_exclaim = "exclaims" @@ -37,6 +37,8 @@ var/throwforce = 0 var/datum/component/orbiter/orbiting var/can_be_z_moved = TRUE + ///If we were without gravity and another animation happened, the bouncing will stop, and we need to restart it in next life(). + var/floating_need_update = FALSE var/zfalling = FALSE @@ -56,10 +58,6 @@ em_block = new(src, render_target) vis_contents += em_block -/atom/movable/Destroy() - QDEL_NULL(em_block) - return ..() - /atom/movable/proc/update_emissive_block() if(blocks_emissive != EMISSIVE_BLOCK_GENERIC) return @@ -183,14 +181,15 @@ return TRUE /atom/movable/proc/stop_pulling() - if(pulling) - pulling.pulledby = null - var/mob/living/ex_pulled = pulling - pulling = null - setGrabState(0) - if(isliving(ex_pulled)) - var/mob/living/L = ex_pulled - L.update_mobility()// mob gets up if it was lyng down in a chokehold + if(!pulling) + return + pulling.pulledby = null + var/mob/living/ex_pulled = pulling + pulling = null + setGrabState(0) + if(isliving(ex_pulled)) + var/mob/living/L = ex_pulled + L.update_mobility()// mob gets up if it was lyng down in a chokehold /atom/movable/proc/Move_Pulled(atom/A) if(!pulling) @@ -232,10 +231,12 @@ /atom/movable/Destroy(force) QDEL_NULL(proximity_monitor) QDEL_NULL(language_holder) + QDEL_NULL(em_block) unbuckle_all_mobs(force=1) . = ..() + if(loc) //Restore air flow if we were blocking it (movables with ATMOS_PASS_PROC will need to do this manually if necessary) if(((CanAtmosPass == ATMOS_PASS_DENSITY && density) || CanAtmosPass == ATMOS_PASS_NO) && isturf(loc)) @@ -493,97 +494,104 @@ /atom/movable/proc/float(on) if(throwing) return - if(on && !(movement_type & FLOATING)) + if(on && (!(movement_type & FLOATING) || floating_need_update)) animate(src, pixel_y = pixel_y + 2, time = 10, loop = -1) sleep(10) animate(src, pixel_y = pixel_y - 2, time = 10, loop = -1) - setMovetype(movement_type | FLOATING) - else if (!on && (movement_type & FLOATING)) + if(!(movement_type & FLOATING)) + setMovetype(movement_type | FLOATING) + else if (!on && movement_type & FLOATING) animate(src, pixel_y = initial(pixel_y), time = 10) setMovetype(movement_type & ~FLOATING) + floating_need_update = FALSE -/* Language procs */ -/atom/movable/proc/get_language_holder(shadow=TRUE) - if(language_holder) - return language_holder - else +/* Language procs +* Unless you are doing something very specific, these are the ones you want to use. +*/ + +/// Gets or creates the relevant language holder. For mindless atoms, gets the local one. For atom with mind, gets the mind one. +/atom/movable/proc/get_language_holder(get_minds = TRUE) + if(!language_holder) language_holder = new initial_language_holder(src) - return language_holder + return language_holder -/atom/movable/proc/grant_language(datum/language/dt, body = FALSE) - var/datum/language_holder/H = get_language_holder(!body) - H.grant_language(dt, body) +/// Grants the supplied language and sets omnitongue true. +/atom/movable/proc/grant_language(language, understood = TRUE, spoken = TRUE, source = LANGUAGE_ATOM) + var/datum/language_holder/LH = get_language_holder() + return LH.grant_language(language, understood, spoken, source) -/atom/movable/proc/grant_all_languages(omnitongue=FALSE) - var/datum/language_holder/H = get_language_holder() - H.grant_all_languages(omnitongue) +/// Grants every language. +/atom/movable/proc/grant_all_languages(understood = TRUE, spoken = TRUE, grant_omnitongue = TRUE, source = LANGUAGE_MIND) + var/datum/language_holder/LH = get_language_holder() + return LH.grant_all_languages(understood, spoken, grant_omnitongue, source) +/// Removes a single language. +/atom/movable/proc/remove_language(language, understood = TRUE, spoken = TRUE, source = LANGUAGE_ALL) + var/datum/language_holder/LH = get_language_holder() + return LH.remove_language(language, understood, spoken, source) + +/// Removes every language and sets omnitongue false. +/atom/movable/proc/remove_all_languages(source = LANGUAGE_ALL, remove_omnitongue = FALSE) + var/datum/language_holder/LH = get_language_holder() + return LH.remove_all_languages(source, remove_omnitongue) + +/// Adds a language to the blocked language list. Use this over remove_language in cases where you will give languages back later. +/atom/movable/proc/add_blocked_language(language, source = LANGUAGE_ATOM) + var/datum/language_holder/LH = get_language_holder() + return LH.add_blocked_language(language, source) + +/// Removes a language from the blocked language list. +/atom/movable/proc/remove_blocked_language(language, source = LANGUAGE_ATOM) + var/datum/language_holder/LH = get_language_holder() + return LH.remove_blocked_language(language, source) + +/// Checks if atom has the language. If spoken is true, only checks if atom can speak the language. +/atom/movable/proc/has_language(language, spoken = FALSE) + var/datum/language_holder/LH = get_language_holder() + return LH.has_language(language, spoken) + +/// Checks if atom can speak the language. +/atom/movable/proc/can_speak_language(language) + var/datum/language_holder/LH = get_language_holder() + return LH.can_speak_language(language) + +/// Returns the result of tongue specific limitations on spoken languages. +/atom/movable/proc/could_speak_language(language) + return TRUE + +/// Returns selected language, if it can be spoken, or finds, sets and returns a new selected language if possible. +/atom/movable/proc/get_selected_language() + var/datum/language_holder/LH = get_language_holder() + return LH.get_selected_language() + +/// Gets a random understood language, useful for hallucinations and such. /atom/movable/proc/get_random_understood_language() - var/datum/language_holder/H = get_language_holder() - . = H.get_random_understood_language() + var/datum/language_holder/LH = get_language_holder() + return LH.get_random_understood_language() -/atom/movable/proc/remove_language(datum/language/dt, body = FALSE) - var/datum/language_holder/H = get_language_holder(!body) - H.remove_language(dt, body) +/// Gets a random spoken language, useful for forced speech and such. +/atom/movable/proc/get_random_spoken_language() + var/datum/language_holder/LH = get_language_holder() + return LH.get_random_spoken_language() -/atom/movable/proc/remove_all_languages() - var/datum/language_holder/H = get_language_holder() - H.remove_all_languages() +/// Copies all languages into the supplied atom/language holder. Source should be overridden when you +/// do not want the language overwritten by later atom updates or want to avoid blocked languages. +/atom/movable/proc/copy_languages(from_holder, source_override) + if(isatom(from_holder)) + var/atom/movable/thing = from_holder + from_holder = thing.get_language_holder() + var/datum/language_holder/LH = get_language_holder() + return LH.copy_languages(from_holder, source_override) -/atom/movable/proc/has_language(datum/language/dt) - var/datum/language_holder/H = get_language_holder() - . = H.has_language(dt) - -/atom/movable/proc/copy_known_languages_from(thing, replace=FALSE) - var/datum/language_holder/H = get_language_holder() - . = H.copy_known_languages_from(thing, replace) - -// Whether an AM can speak in a language or not, independent of whether -// it KNOWS the language -/atom/movable/proc/could_speak_in_language(datum/language/dt) - . = TRUE - -/atom/movable/proc/can_speak_in_language(datum/language/dt) - var/datum/language_holder/H = get_language_holder() - - if(!H.has_language(dt)) - return FALSE - else if(H.omnitongue) - return TRUE - else if(could_speak_in_language(dt) && (!H.only_speaks_language || H.only_speaks_language == dt)) - return TRUE - else - return FALSE - -/atom/movable/proc/get_default_language() - // if no language is specified, and we want to say() something, which - // language do we use? - var/datum/language_holder/H = get_language_holder() - - if(H.selected_default_language) - if(can_speak_in_language(H.selected_default_language)) - return H.selected_default_language - else - H.selected_default_language = null - - - var/datum/language/chosen_langtype - var/highest_priority - - for(var/lt in H.languages) - var/datum/language/langtype = lt - if(!can_speak_in_language(langtype)) - continue - - var/pri = initial(langtype.default_priority) - if(!highest_priority || (pri > highest_priority)) - chosen_langtype = langtype - highest_priority = pri - - H.selected_default_language = . - . = chosen_langtype +/// Empties out the atom specific languages and updates them according to the current atoms language holder. +/// As a side effect, it also creates missing language holders in the process. +/atom/movable/proc/update_atom_languages() + var/datum/language_holder/LH = get_language_holder() + return LH.update_atom_languages(src) /* End language procs */ + + /atom/movable/proc/ConveyorMove(movedir) set waitfor = FALSE if(!anchored && has_gravity()) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index e2c549d911..a7ccada9f2 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -417,7 +417,7 @@ if(player.assigned_role == job) candidates -= player - if(candidates.len < recommended_enemies) + if(candidates.len < recommended_enemies && CONFIG_GET(keyed_list/force_antag_count)[config_tag]) for(var/mob/dead/new_player/player in players) if(player.client && player.ready == PLAYER_READY_TO_PLAY) if(!(role in player.client.prefs.be_special)) // We don't have enough people who want to be antagonist, make a separate list of people who don't want to be one diff --git a/code/game/gamemodes/gangs/dominator.dm b/code/game/gamemodes/gangs/dominator.dm index dca50be5b9..af75315ded 100644 --- a/code/game/gamemodes/gangs/dominator.dm +++ b/code/game/gamemodes/gangs/dominator.dm @@ -48,9 +48,6 @@ /obj/machinery/dominator/hulk_damage() return (max_integrity - integrity_failure) / DOM_HULK_HITS_REQUIRED -/obj/machinery/dominator/tesla_act() - qdel(src) - /obj/machinery/dominator/update_icon() cut_overlays() if(stat & BROKEN) diff --git a/code/game/gamemodes/gangs/gang_decals.dm b/code/game/gamemodes/gangs/gang_decals.dm index 7aaed769d9..a37b4cb63b 100644 --- a/code/game/gamemodes/gangs/gang_decals.dm +++ b/code/game/gamemodes/gangs/gang_decals.dm @@ -10,7 +10,7 @@ /obj/effect/decal/cleanable/crayon/gang icon = 'icons/effects/crayondecal.dmi' layer = ABOVE_NORMAL_TURF_LAYER //Harder to hide - plane = GAME_PLANE + plane = ABOVE_WALL_PLANE do_icon_rotate = FALSE //These are designed to always face south, so no rotation please. var/datum/team/gang/gang diff --git a/code/game/gamemodes/objective_sabotage.dm b/code/game/gamemodes/objective_sabotage.dm index d2cdd2e029..f08d84eae2 100644 --- a/code/game/gamemodes/objective_sabotage.dm +++ b/code/game/gamemodes/objective_sabotage.dm @@ -90,7 +90,10 @@ sabotage_type = "cloner" /datum/sabotage_objective/cloner/check_conditions() - return !(locate(/obj/machinery/clonepod) in GLOB.machines) + for(var/obj/machinery/clonepod/cloner in GLOB.machines) + if(is_station_level(cloner.z)) + return FALSE + return TRUE /datum/sabotage_objective/ai_law name = "Upload a hacked law to the AI." diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 42904383bb..5402c8f41e 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -26,6 +26,8 @@ var/list/chem_buttons //Used when emagged to scramble which chem is used, eg: antitoxin -> morphine var/scrambled_chems = FALSE //Are chem buttons scrambled? used as a warning var/enter_message = "You feel cool air surround you. You go numb as your senses turn inward." + payment_department = ACCOUNT_MED + fair_market_price = 5 /obj/machinery/sleeper/Initialize() . = ..() @@ -35,6 +37,11 @@ reset_chem_buttons() RefreshParts() add_inital_chems() + new_occupant_dir = dir + +/obj/machinery/sleeper/setDir(newdir) + . = ..() + new_occupant_dir = dir /obj/machinery/sleeper/on_deconstruction() var/obj/item/reagent_containers/sleeper_buffer/buffer = new (loc) @@ -205,6 +212,13 @@ ui = new(user, src, ui_key, "sleeper", name, 550, 700, master_ui, state) ui.open() +/obj/machinery/sleeper/process() + ..() + check_nap_violations() + +/obj/machinery/sleeper/nap_violation(mob/violator) + open_machine() + /obj/machinery/sleeper/ui_data() var/list/data = list() var/chemical_list = list() @@ -250,7 +264,7 @@ data["occupant"]["fireLoss"] = mob_occupant.getFireLoss() data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss() data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN) - + if(mob_occupant.reagents.reagent_list.len) for(var/datum/reagent/R in mob_occupant.reagents.reagent_list) chemical_list += list(list("name" = R.name, "volume" = R.volume)) @@ -290,7 +304,7 @@ if(..()) return var/mob/living/mob_occupant = occupant - + check_nap_violations() switch(action) if("door") if(state_open) @@ -420,3 +434,45 @@ /obj/machinery/sleeper/old icon_state = "oldpod" + +/obj/machinery/sleeper/party + name = "party pod" + desc = "'Sleeper' units were once known for their healing properties, until a lengthy investigation revealed they were also dosing patients with deadly lead acetate. This appears to be one of those old 'sleeper' units repurposed as a 'Party Pod'. It’s probably not a good idea to use it." + icon_state = "partypod" + idle_power_usage = 3000 + circuit = /obj/item/circuitboard/machine/sleeper/party + var/leddit = FALSE //Get it like reddit and lead alright fine + ui_x = 310 + ui_y = 400 + + controls_inside = TRUE + possible_chems = list( + list(/datum/reagent/consumable/ethanol/beer, /datum/reagent/consumable/laughter), + list(/datum/reagent/spraytan,/datum/reagent/barbers_aid), + list(/datum/reagent/colorful_reagent,/datum/reagent/hair_dye), + list(/datum/reagent/drug/space_drugs,/datum/reagent/baldium) + )//Exclusively uses non-lethal, "fun" chems. At an obvious downside. + var/spray_chems = list( + /datum/reagent/spraytan, /datum/reagent/hair_dye, /datum/reagent/baldium, /datum/reagent/barbers_aid + )//Chemicals that need to have a touch or vapor reaction to be applied, not the standard chamber reaction. + enter_message = "You're surrounded by some funky music inside the chamber. You zone out as you feel waves of krunk vibe within you." + +/obj/machinery/sleeper/party/inject_chem(chem, mob/user) + if(leddit) + occupant.reagents.add_reagent(/datum/reagent/toxin/leadacetate, 4) //You're injecting chemicals into yourself from a recalled, decrepit medical machine. What did you expect? + else if (prob(20)) + occupant.reagents.add_reagent(/datum/reagent/toxin/leadacetate, rand(1,3)) + if(chem in spray_chems) + var/datum/reagents/holder = new() + holder.add_reagent(chem_buttons[chem], 10) //I hope this is the correct way to do this. + holder.reaction(occupant, VAPOR, 0) + holder.trans_to(occupant, 10) + playsound(src.loc, 'sound/effects/spray2.ogg', 50, TRUE, -6) + if(user) + log_combat(user, occupant, "sprayed [chem] into", addition = "via [src]") + return TRUE + ..() + +/obj/machinery/sleeper/party/emag_act(mob/user) + ..() + leddit = TRUE diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 995d11acb7..e2f26d6617 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -110,7 +110,8 @@ Class Procs: var/state_open = FALSE var/critical_machine = FALSE //If this machine is critical to station operation and should have the area be excempted from power failures. var/list/occupant_typecache //if set, turned into typecache in Initialize, other wise, defaults to mob/living typecache - var/atom/movable/occupant = null + var/atom/movable/occupant + var/new_occupant_dir = SOUTH //The direction the occupant will be set to look at when entering the machine. var/speed_process = FALSE // Process as fast as possible? var/obj/item/circuitboard/circuit // Circuit to be created and inserted when the machinery is created // For storing and overriding ui id and dimensions @@ -121,6 +122,10 @@ Class Procs: var/interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE + var/fair_market_price = 69 + var/market_verb = "Customer" + var/payment_department = ACCOUNT_ENG + /obj/machinery/Initialize() if(!armor) armor = list("melee" = 25, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70) @@ -213,6 +218,7 @@ Class Procs: if(target && !target.has_buckled_mobs() && (!isliving(target) || !mobtarget.buckled)) occupant = target target.forceMove(src) + target.setDir(new_occupant_dir) updateUsrDialog() update_icon() @@ -248,6 +254,36 @@ Class Procs: return FALSE return TRUE +/obj/machinery/proc/check_nap_violations() + if(!SSeconomy.full_ancap) + return TRUE + if(occupant && !state_open) + if(ishuman(occupant)) + var/mob/living/carbon/human/H = occupant + var/obj/item/card/id/I = H.get_idcard() + if(I) + var/datum/bank_account/insurance = I.registered_account + if(!insurance) + say("[market_verb] NAP Violation: No bank account found.") + nap_violation() + return FALSE + else + if(!insurance.adjust_money(-fair_market_price)) + say("[market_verb] NAP Violation: Unable to pay.") + nap_violation() + return FALSE + var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department) + if(D) + D.adjust_money(fair_market_price) + else + say("[market_verb] NAP Violation: No ID card found.") + nap_violation() + return FALSE + return TRUE + +/obj/machinery/proc/nap_violation(mob/violator) + return + //////////////////////////////////////////////////////////////////////////////////////////// //Return a non FALSE value to interrupt attack_hand propagation to subtypes. @@ -486,11 +522,11 @@ Class Procs: /obj/machinery/proc/can_be_overridden() . = 1 -/obj/machinery/tesla_act(power, tesla_flags, shocked_objects) - ..() - if(prob(85) && (tesla_flags & TESLA_MACHINE_EXPLOSIVE)) +/obj/machinery/zap_act(power, zap_flags, shocked_objects) + . = ..() + if(prob(85) && (zap_flags & ZAP_MACHINE_EXPLOSIVE)) explosion(src, 1, 2, 4, flame_range = 2, adminlog = FALSE, smoke = FALSE) - if(tesla_flags & TESLA_OBJ_DAMAGE) + else if(zap_flags & ZAP_OBJ_DAMAGE) take_damage(power/2000, BURN, "energy") if(prob(40)) emp_act(EMP_LIGHT) diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index de92e1c249..3b32213509 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -17,7 +17,6 @@ var/list/L = list() var/list/LL = list() var/hacked = FALSE - var/hackable = TRUE var/disabled = 0 var/shocked = FALSE var/hack_wire @@ -31,8 +30,10 @@ var/list/datum/design/matching_designs var/selected_category var/screen = 1 + var/base_price = 25 + var/hacked_price = 50 - var/datum/techweb/stored_research = /datum/techweb/specialized/autounlocking/autolathe + var/datum/techweb/specialized/autounlocking/stored_research = /datum/techweb/specialized/autounlocking/autolathe var/list/categories = list( "Tools", "Electronics", @@ -425,11 +426,11 @@ /obj/machinery/autolathe/proc/adjust_hacked(state) hacked = state - if(!hackable && hacked) - return for(var/id in SSresearch.techweb_designs) var/datum/design/D = SSresearch.techweb_design_by_id(id) - if((D.build_type & AUTOLATHE) && ("hacked" in D.category)) + if(D.build_type & stored_research.design_autounlock_skip_types) + continue + if((D.build_type & stored_research.design_autounlock_buildtypes) && ("hacked" in D.category)) if(hacked) stored_research.add_design(D) else @@ -441,8 +442,7 @@ /obj/machinery/autolathe/secure name = "secured autolathe" - desc = "An autolathe reprogrammed with security protocols to prevent hacking." - hackable = FALSE + desc = "It produces items using metal and glass. This model was reprogrammed without some of the more hazardous designs." circuit = /obj/item/circuitboard/machine/autolathe/secure stored_research = /datum/techweb/specialized/autounlocking/autolathe/public base_print_speed = 20 diff --git a/code/game/machinery/bank_machine.dm b/code/game/machinery/bank_machine.dm index 41867a8520..2b683f16a3 100644 --- a/code/game/machinery/bank_machine.dm +++ b/code/game/machinery/bank_machine.dm @@ -8,6 +8,7 @@ var/obj/item/radio/radio var/radio_channel = RADIO_CHANNEL_COMMON var/minimum_time_between_warnings = 400 + var/syphoning_credits = 0 /obj/machinery/computer/bank_machine/Initialize() . = ..() @@ -25,9 +26,14 @@ if(istype(I, /obj/item/stack/spacecash)) var/obj/item/stack/spacecash/C = I value = C.value * C.amount + else if(istype(I, /obj/item/holochip)) + var/obj/item/holochip/H = I + value = H.credits if(value) - SSshuttle.points += value - to_chat(user, "You deposit [I]. The station now has [SSshuttle.points] credits.") + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + if(D) + D.adjust_money(value) + to_chat(user, "You deposit [I]. The Cargo Budget is now [D.account_balance] cr.") qdel(I) return return ..() @@ -38,14 +44,16 @@ if(siphoning) if (stat & (BROKEN|NOPOWER)) say("Insufficient power. Halting siphon.") - siphoning = FALSE - if(SSshuttle.points < 200) - say("Station funds depleted. Halting siphon.") - siphoning = FALSE - else - new /obj/item/stack/spacecash/c200(drop_location()) // will autostack - playsound(src.loc, 'sound/items/poster_being_created.ogg', 100, 1) - SSshuttle.points -= 200 + end_syphon() + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + if(!D.has_money(200)) + say("Cargo budget depleted. Halting siphon.") + end_syphon() + return + + playsound(src.loc, 'sound/items/poster_being_created.ogg', 100, 1) + syphoning_credits += 200 + D.adjust_money(-200) if(next_warning < world.time && prob(15)) var/area/A = get_area(loc) var/message = "Unauthorized credit withdrawal underway in [A.map_name]!!" @@ -61,7 +69,8 @@ /obj/machinery/computer/bank_machine/ui_data(mob/user) var/list/data = list() - data["current_balance"] = SSshuttle.points + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + data["current_balance"] = D.account_balance data["siphoning"] = siphoning data["station_name"] = station_name() @@ -78,5 +87,10 @@ . = TRUE if("halt") say("Station credit withdrawal halted.") - siphoning = FALSE + end_syphon() . = TRUE + +/obj/machinery/computer/bank_machine/proc/end_syphon() + siphoning = FALSE + new /obj/item/holochip(drop_location(), syphoning_credits) //get the loot + syphoning_credits = 0 diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm index 3a90707bbe..71de04ee99 100644 --- a/code/game/machinery/buttons.dm +++ b/code/game/machinery/buttons.dm @@ -16,10 +16,13 @@ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF /obj/machinery/button/Initialize(mapload, ndir = 0, built = 0) - if(istext(id) && mapload) - if(copytext(id, 1, 2) == "!") - id = SSmapping.get_obfuscated_id(id) + if(istext(id) && mapload && id[1] == "!") + id = SSmapping.get_obfuscated_id(id) . = ..() + var/turf/T = get_turf_pixel(src) + if(iswallturf(T)) + plane = ABOVE_WALL_PLANE + if(built) setDir(ndir) pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) @@ -27,7 +30,6 @@ panel_open = TRUE update_icon() - if(!built && !device && device_type) device = new device_type(src) diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index 1766391709..b6af0600e4 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -48,8 +48,7 @@ if(2) // State 2 if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C = W - if(C.use(2)) + if(W.use_tool(src, user, 0, 2)) to_chat(user, "You add wires to the assembly.") state = 3 else diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index 021232f435..33e250fa59 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -75,7 +75,7 @@ // UPGRADE PROCS /obj/machinery/camera/proc/upgradeEmpProof() - AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS) + AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS) assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/plasma(assembly)) upgrades |= CAMERA_UPGRADE_EMP_PROOF diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 3f4b389b77..cfe9d14663 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -37,6 +37,9 @@ var/list/unattached_flesh var/flesh_number = 0 + var/datum/bank_account/current_insurance + fair_market_price = 5 // He nodded, because he knew I was right. Then he swiped his credit card to pay me for arresting him. + payment_department = ACCOUNT_MED /obj/machinery/clonepod/Initialize() . = ..() @@ -131,7 +134,7 @@ return examine(user) //Start growing a human clone in the pod! -/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, datum/species/mrace, list/features, factions, list/quirks) +/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance) if(panel_open) return FALSE if(mess || attempting) @@ -161,7 +164,7 @@ mess = TRUE update_icon() return FALSE - + current_insurance = insurance attempting = TRUE //One at a time!! countdown.start() @@ -224,15 +227,29 @@ connected_message("Clone Ejected: Loss of power.") else if(mob_occupant && (mob_occupant.loc == src)) - if((mob_occupant.stat == DEAD) || (mob_occupant.suiciding) || mob_occupant.hellbound) //Autoeject corpses and suiciding dudes. - connected_message("Clone Rejected: Deceased.") + if(SSeconomy.full_ancap) + if(!current_insurance) + go_out() + connected_message("Clone Ejected: No bank account.") + if(internal_radio) + SPEAK("The cloning of [mob_occupant.real_name] has been terminated due to no bank account to draw payment from.") + else if(!current_insurance.adjust_money(-fair_market_price)) + go_out() + connected_message("Clone Ejected: Out of Money.") + if(internal_radio) + SPEAK("The cloning of [mob_occupant.real_name] has been ended prematurely due to being unable to pay.") + else + var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department) + if(D) + D.adjust_money(fair_market_price) + if(mob_occupant && (mob_occupant.stat == DEAD) || (mob_occupant.suiciding) || mob_occupant.hellbound) //Autoeject corpses and suiciding dudes. connected_message("Clone Rejected: Deceased.") if(internal_radio) SPEAK("The cloning has been \ aborted due to unrecoverable tissue failure.") go_out() mob_occupant.copy_from_prefs_vr() - else if(mob_occupant.cloneloss > (100 - heal_level)) + else if(mob_occupant && mob_occupant.cloneloss > (100 - heal_level)) mob_occupant.Unconscious(80) var/dmg_mult = CONFIG_GET(number/damage_multiplier) //Slowly get that clone healed and finished. @@ -259,7 +276,7 @@ use_power(7500) //This might need tweaking. - else if((mob_occupant.cloneloss <= (100 - heal_level))) + else if((mob_occupant && mob_occupant.cloneloss <= (100 - heal_level))) connected_message("Cloning Process Complete.") if(internal_radio) SPEAK("The cloning cycle is complete.") @@ -368,7 +385,7 @@ if(!mob_occupant) return - + current_insurance = null REMOVE_TRAIT(mob_occupant, TRAIT_STABLEHEART, CLONING_POD_TRAIT) REMOVE_TRAIT(mob_occupant, TRAIT_MUTATION_STASIS, CLONING_POD_TRAIT) REMOVE_TRAIT(mob_occupant, TRAIT_STABLELIVER, CLONING_POD_TRAIT) diff --git a/code/game/machinery/computer/arcade/orion_trail.dm b/code/game/machinery/computer/arcade/orion_trail.dm index 2304312953..8b81c69ed2 100644 --- a/code/game/machinery/computer/arcade/orion_trail.dm +++ b/code/game/machinery/computer/arcade/orion_trail.dm @@ -117,7 +117,7 @@ if(food <= 0) dat += "
You ran out of food and starved." if(obj_flags & EMAGGED) - user.nutrition = 0 //yeah you pretty hongry + user.set_nutrition(0) //yeah you pretty hongry to_chat(user, "Your body instantly contracts to that of one who has not eaten in months. Agonizing cramps seize you as you fall to the floor.") if(fuel <= 0) dat += "
You ran out of fuel, and drift, slowly, into a star." diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index eb7f194229..450967050c 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -175,6 +175,12 @@ clockwork = TRUE //it'd look very weird light_power = 0 +/obj/machinery/computer/security/telescreen/Initialize() + . = ..() + var/turf/T = get_turf_pixel(src) + if(iswallturf(T)) + plane = ABOVE_WALL_PLANE + /obj/machinery/computer/security/telescreen/update_icon_state() icon_state = initial(icon_state) if(stat & BROKEN) diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index b0e80b63d2..74cceacd12 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -467,7 +467,8 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) to_chat(usr, "No log exists for this job.") updateUsrDialog() return - + if(inserted_modify_id.registered_account) + inserted_modify_id.registered_account.account_job = jobdatum // this is a terrible idea and people will grief but sure whatever inserted_modify_id.access = ( istype(src, /obj/machinery/computer/card/centcom) ? get_centcom_access(t1) : jobdatum.get_access() ) if (inserted_modify_id) inserted_modify_id.assignment = t1 diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 07cc252b87..981a5643a8 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -73,7 +73,7 @@ if(pod.occupant) continue //how though? - if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"])) + if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"])) temp = "[R.fields["name"]] => Cloning cycle in progress..." records -= R @@ -415,7 +415,7 @@ else if(pod.occupant) temp = "Cloning cycle already in progress." playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"])) + else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"])) temp = "[C.fields["name"]] => Cloning cycle in progress..." playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) records.Remove(C) @@ -441,9 +441,13 @@ /obj/machinery/computer/cloning/proc/scan_occupant(occupant) var/mob/living/mob_occupant = get_mob_or_brainmob(occupant) var/datum/dna/dna + var/datum/bank_account/has_bank_account if(ishuman(mob_occupant)) var/mob/living/carbon/C = mob_occupant dna = C.has_dna() + var/obj/item/card/id/I = C.get_idcard() + if(I) + has_bank_account = I.registered_account if(isbrain(mob_occupant)) var/mob/living/brain/B = mob_occupant dna = B.stored_dna @@ -468,7 +472,10 @@ scantemp = "Subject already in database." playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) return - + if(SSeconomy.full_ancap && !has_bank_account) + scantemp = "Subject is either missing an ID card with a bank account on it, or does not have an account to begin with. Please ensure the ID card is on the body before attempting to scan." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + return var/datum/data/record/R = new() if(dna.species) // We store the instance rather than the path, because some @@ -490,6 +497,7 @@ R.fields["features"] = dna.features R.fields["factions"] = mob_occupant.faction R.fields["quirks"] = list() + R.fields["bank_account"] = has_bank_account for(var/V in mob_occupant.roundstart_quirks) var/datum/quirk/T = V R.fields["quirks"][T.type] = T.clone_data() diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 6eb06e3be4..22bea14381 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -163,11 +163,15 @@ else if(!S.prerequisites_met()) to_chat(usr, "You have not met the requirements for purchasing this shuttle.") else - if(SSshuttle.points >= S.credit_cost) + var/points_to_check + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + if(D) + points_to_check = D.account_balance + if(points_to_check >= S.credit_cost) var/obj/machinery/shuttle_manipulator/M = locate() in GLOB.machines if(M) SSshuttle.shuttle_purchased = TRUE - SSshuttle.points -= S.credit_cost + D.adjust_money(-S.credit_cost) minor_announce("[usr.real_name] has purchased [S.name] for [S.credit_cost] credits." , "Shuttle Purchase") message_admins("[ADMIN_LOOKUPFLW(usr)] purchased [S.name].") SSblackbox.record_feedback("text", "shuttle_purchase", 1, "[S.name]") @@ -576,7 +580,8 @@ dat += "
Lift access restrictions on maintenance and external airlocks?
\[ OK | Cancel \]" if(STATE_PURCHASE) - dat += "Budget: [SSshuttle.points] Credits.
" + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + dat += "Budget: [D.account_balance] Credits.
" dat += "
" dat += "Caution: Purchasing dangerous shuttles may lead to mutiny and/or death.
" dat += "
" diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index b007bc0161..5ee8223625 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -83,7 +83,6 @@ if(istype(P, /obj/item/stack/cable_coil)) if(!P.tool_start_check(user, amount=5)) return - to_chat(user, "You start to add cables to the frame...") if(P.use_tool(src, user, 20, volume=50, amount=5)) to_chat(user, "You add cables to the frame.") diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 07f95c17ff..9330a30555 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -242,6 +242,7 @@ if((isnull(user) || istype(user)) && state_open && !panel_open) ..(user) var/mob/living/mob_occupant = occupant + investigate_log("Cryogenics machine closed with occupant [key_name(occupant)] by user [key_name(user)].", INVESTIGATE_CRYOGENICS) if(mob_occupant && mob_occupant.stat != DEAD) to_chat(occupant, "You feel cool air surround you. You go numb as your senses turn inward.") if(mob_occupant.client)//if they're logged in @@ -251,12 +252,15 @@ icon_state = "cryopod" /obj/machinery/cryopod/open_machine() + if(occupant) + investigate_log("Cryogenics machine opened with occupant [key_name(occupant)] inside.", INVESTIGATE_CRYOGENICS) ..() icon_state = "cryopod-open" density = TRUE name = initial(name) /obj/machinery/cryopod/container_resist(mob/living/user) + investigate_log("Cryogenics machine container resisted by [key_name(user)] with occupant [key_name(occupant)].", INVESTIGATE_CRYOGENICS) visible_message("[occupant] emerges from [src]!", "You climb out of [src]!") open_machine() @@ -304,6 +308,8 @@ var/mob/living/mob_occupant = occupant var/list/obj/item/cryo_items = list() + + investigate_log("Despawning [key_name(mob_occupant)].", INVESTIGATE_CRYOGENICS) //Handle Borg stuff first if(iscyborg(mob_occupant)) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 3bc8aff809..4c12809184 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -470,15 +470,15 @@ if(welded) weld_overlay = get_airlock_overlay("welded", overlays_file) if(obj_integrity < integrity_failure * max_integrity) - damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) + damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) else if(obj_integrity < (0.75 * max_integrity)) - damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) + damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) if(lights && hasPower()) if(locked) - lights_overlay = get_airlock_overlay("lights_bolts", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) + lights_overlay = get_airlock_overlay("lights_bolts", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) else if(emergency) - lights_overlay = get_airlock_overlay("lights_emergency", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) + lights_overlay = get_airlock_overlay("lights_emergency", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) if(note) note_overlay = get_airlock_overlay(notetype, note_overlay_file) @@ -496,18 +496,18 @@ else panel_overlay = get_airlock_overlay("panel_closed", overlays_file) if(obj_integrity < integrity_failure * max_integrity) - damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) + damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) else if(obj_integrity < (0.75 * max_integrity)) - damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) + damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) if(welded) weld_overlay = get_airlock_overlay("welded", overlays_file) - lights_overlay = get_airlock_overlay("lights_denied", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) + lights_overlay = get_airlock_overlay("lights_denied", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) if(note) note_overlay = get_airlock_overlay(notetype, note_overlay_file) if(AIRLOCK_EMAG) frame_overlay = get_airlock_overlay("closed", icon) - sparks_overlay = get_airlock_overlay("sparks", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) + sparks_overlay = get_airlock_overlay("sparks", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) if(airlock_material) filling_overlay = get_airlock_overlay("[airlock_material]_closed", overlays_file) else @@ -518,9 +518,9 @@ else panel_overlay = get_airlock_overlay("panel_closed", overlays_file) if(obj_integrity < integrity_failure * max_integrity) - damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) + damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) else if(obj_integrity < (0.75 * max_integrity)) - damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) + damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) if(welded) weld_overlay = get_airlock_overlay("welded", overlays_file) if(note) @@ -533,7 +533,7 @@ else filling_overlay = get_airlock_overlay("fill_closing", icon) if(lights && hasPower()) - lights_overlay = get_airlock_overlay("lights_closing", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) + lights_overlay = get_airlock_overlay("lights_closing", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) if(panel_open) if(security_level) panel_overlay = get_airlock_overlay("panel_closing_protected", overlays_file) @@ -554,7 +554,7 @@ else panel_overlay = get_airlock_overlay("panel_open", overlays_file) if(obj_integrity < (0.75 * max_integrity)) - damag_overlay = get_airlock_overlay("sparks_open", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) + damag_overlay = get_airlock_overlay("sparks_open", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) if(note) note_overlay = get_airlock_overlay("[notetype]_open", note_overlay_file) @@ -565,7 +565,7 @@ else filling_overlay = get_airlock_overlay("fill_opening", icon) if(lights && hasPower()) - lights_overlay = get_airlock_overlay("lights_opening", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE) + lights_overlay = get_airlock_overlay("lights_opening", overlays_file, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE) if(panel_open) if(security_level) panel_overlay = get_airlock_overlay("panel_opening_protected", overlays_file) diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm index 7b90715f2b..fed54f55f8 100644 --- a/code/game/machinery/doors/airlock_electronics.dm +++ b/code/game/machinery/doors/airlock_electronics.dm @@ -1,6 +1,7 @@ /obj/item/electronics/airlock name = "airlock electronics" req_access = list(ACCESS_MAINT_TUNNELS) + custom_price = 50 var/list/accesses = list() var/one_access = 0 diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index cd22b2dc05..1d39372dec 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -21,6 +21,7 @@ icon = 'icons/obj/status_display.dmi' icon_state = "frame" desc = "A remote control for a door." + plane = ABOVE_WALL_PLANE req_access = list(ACCESS_SECURITY) density = FALSE var/id // id of linked machinery/lockers diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index c4c712ca25..98a888fa66 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -290,8 +290,6 @@ operating = TRUE do_animate("closing") layer = closingLayer - if(!safe) - crush() sleep(5) density = TRUE sleep(5) @@ -303,6 +301,8 @@ update_freelook_sight() if(safe) CheckForMobs() + else + crush() return 1 /obj/machinery/door/proc/CheckForMobs() diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 1b83bb4b96..915fad6418 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -260,6 +260,7 @@ /obj/item/electronics/firelock name = "firelock circuitry" + custom_price = 50 desc = "A circuit board used in construction of firelocks." icon_state = "mainboard" @@ -400,12 +401,11 @@ "You begin adding wires to [src]...") playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) if(do_after(user, 60, target = src)) - if(constructionStep != CONSTRUCTION_GUTTED || B.get_amount() < 5 || !B) + if(constructionStep != CONSTRUCTION_GUTTED || !B.use_tool(src, user, 0, 5)) return user.visible_message("[user] adds wires to [src].", \ "You wire [src].") playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) - B.use(5) constructionStep = CONSTRUCTION_WIRES_EXPOSED update_icon() return diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index db806ef3ac..a9c411c634 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -174,9 +174,11 @@ GLOBAL_LIST_EMPTY(doppler_arrays) else linked_techweb.largest_bomb_value = TECHWEB_BOMB_POINTCAP point_gain = 1000 - + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_SCI) + if(D) + D.adjust_money(point_gain) linked_techweb.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, point_gain) - say("Gained [point_gain] points from explosion dataset.") + say("Explosion details and mixture analyzed and sold to the highest bidder for [point_gain] cr, with a reward of [point_gain] points.") else //you've made smaller bombs say("Data already captured. Aborting.") diff --git a/code/game/machinery/embedded_controller/simple_vent_controller.dm b/code/game/machinery/embedded_controller/simple_vent_controller.dm index 6c8467dbd3..6416de70f1 100644 --- a/code/game/machinery/embedded_controller/simple_vent_controller.dm +++ b/code/game/machinery/embedded_controller/simple_vent_controller.dm @@ -34,7 +34,7 @@ /obj/machinery/embedded_controller/radio/simple_vent_controller icon = 'icons/obj/airlock_machines.dmi' icon_state = "airlock_control_standby" - + plane = ABOVE_WALL_PLANE name = "vent controller" density = FALSE diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index f4f308c490..8869ea396e 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -2,6 +2,7 @@ /obj/item/electronics/firealarm name = "fire alarm electronics" + custom_price = 50 desc = "A fire alarm circuit. Can handle heat levels up to 40 degrees celsius." /obj/item/wallframe/firealarm @@ -16,6 +17,7 @@ desc = "\"Pull this in case of emergency\". Thus, keep pulling it forever." icon = 'icons/obj/monitors.dmi' icon_state = "fire0" + plane = ABOVE_WALL_PLANE max_integrity = 250 integrity_failure = 0.4 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30) @@ -205,11 +207,9 @@ return if(1) if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/coil = W - if(coil.get_amount() < 5) + if(!W.use_tool(src, user, 0, 5)) to_chat(user, "You need more cable for this!") else - coil.use(5) buildstage = 2 to_chat(user, "You wire \the [src].") update_icon() diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index 7bef255aff..f4f1aa0637 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -5,6 +5,7 @@ desc = "A wall-mounted flashbulb device." icon = 'icons/obj/stationobjs.dmi' icon_state = "mflash1" + plane = ABOVE_WALL_PLANE max_integrity = 250 integrity_failure = 0.4 light_color = LIGHT_COLOR_WHITE @@ -20,6 +21,7 @@ name = "portable flasher" desc = "A portable flashing device. Wrench to activate and deactivate. Cannot detect slow movements." icon_state = "pflash1-p" + plane = GAME_PLANE strength = 80 anchored = FALSE base_state = "pflash" diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm index 244c300905..141f261688 100644 --- a/code/game/machinery/harvester.dm +++ b/code/game/machinery/harvester.dm @@ -20,6 +20,11 @@ . = ..() if(prob(1)) name = "auto-autopsy" + new_occupant_dir = dir + +/obj/machinery/harvester/setDir(newdir) + . = ..() + new_occupant_dir = dir /obj/machinery/harvester/RefreshParts() interval = 0 diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 067f10fa0f..621e486e90 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -34,7 +34,7 @@ GLOBAL_LIST_EMPTY(network_holopads) desc = "It's a floor-mounted device for projecting holographic images." icon_state = "holopad0" layer = LOW_OBJ_LAYER - plane = FLOOR_PLANE + plane = ABOVE_WALL_PLANE flags_1 = HEAR_1 use_power = IDLE_POWER_USE idle_power_usage = 5 @@ -396,7 +396,6 @@ GLOBAL_LIST_EMPTY(network_holopads) Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY) Hologram.Impersonation = user - Hologram.copy_known_languages_from(user,replace = TRUE) Hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it. Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them. Hologram.setAnchored(TRUE)//So space wind cannot drag it. @@ -555,9 +554,8 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ Hologram.alpha = 170 Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY) Hologram.dir = SOUTH //for now - Hologram.grant_all_languages(omnitongue=TRUE) var/datum/language_holder/holder = Hologram.get_language_holder() - holder.selected_default_language = record.language + holder.selected_language = record.language Hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it. Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them. Hologram.setAnchored(TRUE)//So space wind cannot drag it. @@ -649,7 +647,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ return if(HOLORECORD_LANGUAGE) var/datum/language_holder/holder = replay_holo.get_language_holder() - holder.selected_default_language = entry[2] + holder.selected_language = entry[2] if(HOLORECORD_PRESET) var/preset_type = entry[2] var/datum/preset_holoimage/H = new preset_type @@ -672,6 +670,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ updateDialog() /obj/effect/overlay/holo_pad_hologram + initial_language_holder = /datum/language_holder/universal var/mob/living/Impersonation var/datum/holocall/HC diff --git a/code/game/machinery/hypnochair.dm b/code/game/machinery/hypnochair.dm new file mode 100644 index 0000000000..1b57f61b79 --- /dev/null +++ b/code/game/machinery/hypnochair.dm @@ -0,0 +1,205 @@ +/obj/machinery/hypnochair + name = "enhanced interrogation chamber" + desc = "A device used to perform \"enhanced interrogation\" through invasive mental conditioning." + icon = 'icons/obj/machines/implantchair.dmi' + icon_state = "hypnochair" + circuit = /obj/item/circuitboard/machine/hypnochair + density = TRUE + opacity = 0 + ui_x = 375 + ui_y = 480 + var/mob/living/carbon/victim = null ///Keeps track of the victim to apply effects if it teleports away + var/interrogating = FALSE ///Is the device currently interrogating someone? + var/start_time = 0 ///Time when the interrogation was started, to calculate effect in case of interruption + var/trigger_phrase = "" ///Trigger phrase to implant + var/timerid = 0 ///Timer ID for interrogations + + var/message_cooldown = 0 ///Cooldown for breakout message + +/obj/machinery/hypnochair/Initialize() + . = ..() + open_machine() + update_icon() + +/obj/machinery/hypnochair/attackby(obj/item/I, mob/user, params) + if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I)) + update_icon() + return + + if(default_pry_open(I)) + return + + if(default_deconstruction_crowbar(I)) + return + + return ..() + +/obj/machinery/hypnochair/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "hypnochair", name, ui_x, ui_y, master_ui, state) + ui.open() + +/obj/machinery/hypnochair/ui_data() + var/list/data = list() + data["occupied"] = occupant ? TRUE : FALSE + data["open"] = state_open + data["interrogating"] = interrogating + + data["occupant"] = list() + if(occupant) + var/mob/living/mob_occupant = occupant + data["occupant"]["name"] = mob_occupant.name + data["occupant"]["stat"] = mob_occupant.stat + + data["trigger"] = trigger_phrase + + return data + +/obj/machinery/hypnochair/ui_act(action, params) + if(..()) + return + switch(action) + if("door") + if(state_open) + close_machine() + else + if(!interrogating) + open_machine() + . = TRUE + if("set_phrase") + set_phrase(params["phrase"]) + . = TRUE + if("interrogate") + if(!interrogating) + interrogate() + else + interrupt_interrogation() + . = TRUE + +/obj/machinery/hypnochair/proc/set_phrase(phrase) + trigger_phrase = phrase + +/obj/machinery/hypnochair/proc/interrogate() + if(!trigger_phrase) + playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 25, TRUE) + return + var/mob/living/carbon/C = occupant + if(!istype(C)) + playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 25, TRUE) + return + victim = C + if(!(C.get_eye_protection() > 0)) + to_chat(C, "Strobing coloured lights assault you relentlessly! You're losing your ability to think straight!") + C.become_blind("hypnochair") + ADD_TRAIT(C, TRAIT_DEAF, "hypnochair") + interrogating = TRUE + START_PROCESSING(SSobj, src) + start_time = world.time + update_icon() + timerid = addtimer(CALLBACK(src, .proc/finish_interrogation), 450, TIMER_STOPPABLE) + +/obj/machinery/hypnochair/process() + var/mob/living/carbon/C = occupant + if(!istype(C) || C != victim) + interrupt_interrogation() + return + if(prob(10) && !(C.get_eye_protection() > 0)) + to_chat(C, "[pick(\ + "...blue... red... green... blue, red, green, blueredgreenblueredgreen",\ + "...pretty colors...",\ + "...you keep hearing words, but you can't seem to understand them...",\ + "...so peaceful...",\ + "...an annoying buzz in your ears..."\ + )]") + +/obj/machinery/hypnochair/proc/finish_interrogation() + interrogating = FALSE + STOP_PROCESSING(SSobj, src) + update_icon() + var/temp_trigger = trigger_phrase + trigger_phrase = "" //Erase evidence, in case the subject is able to look at the panel afterwards + audible_message("[src] pings!") + playsound(src, 'sound/machines/ping.ogg', 30, TRUE) + + if(QDELETED(victim) || victim != occupant) + victim = null + return + victim.cure_blind("hypnochair") + REMOVE_TRAIT(victim, TRAIT_DEAF, "hypnochair") + if(!(victim.get_eye_protection() > 0)) + victim.cure_trauma_type(/datum/brain_trauma/severe/hypnotic_trigger, TRAUMA_RESILIENCE_SURGERY) + if(prob(90)) + victim.gain_trauma(new /datum/brain_trauma/severe/hypnotic_trigger(temp_trigger), TRAUMA_RESILIENCE_SURGERY) + else + victim.gain_trauma(new /datum/brain_trauma/severe/hypnotic_stupor(), TRAUMA_RESILIENCE_SURGERY) + victim = null + +/obj/machinery/hypnochair/proc/interrupt_interrogation() + deltimer(timerid) + interrogating = FALSE + STOP_PROCESSING(SSobj, src) + update_icon() + + if(QDELETED(victim)) + victim = null + return + victim.cure_blind("hypnochair") + REMOVE_TRAIT(victim, TRAIT_DEAF, "hypnochair") + if(!(victim.get_eye_protection() > 0)) + var/time_diff = world.time - start_time + switch(time_diff) + if(0 to 100) + victim.confused += 10 + victim.Dizzy(100) + victim.blur_eyes(5) + if(101 to 200) + victim.confused += 15 + victim.Dizzy(200) + victim.blur_eyes(10) + if(prob(25)) + victim.apply_status_effect(/datum/status_effect/trance, rand(50,150), FALSE) + if(201 to INFINITY) + victim.confused += 20 + victim.Dizzy(300) + victim.blur_eyes(15) + if(prob(65)) + victim.apply_status_effect(/datum/status_effect/trance, rand(50,150), FALSE) + victim = null + +/obj/machinery/hypnochair/update_icon_state() + icon_state = initial(icon_state) + if(state_open) + icon_state += "_open" + if(occupant) + if(interrogating) + icon_state += "_active" + else + icon_state += "_occupied" + +/obj/machinery/hypnochair/container_resist(mob/living/user) + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + user.visible_message("You see [user] kicking against the door of [src]!", \ + "You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(600)].)", \ + "You hear a metallic creaking from [src].") + if(do_after(user,(600), target = src)) + if(!user || user.stat != CONSCIOUS || user.loc != src || state_open) + return + user.visible_message("[user] successfully broke out of [src]!", \ + "You successfully break out of [src]!") + open_machine() + +/obj/machinery/hypnochair/relaymove(mob/user) + if(message_cooldown <= world.time) + message_cooldown = world.time + 50 + to_chat(user, "[src]'s door won't budge!") + +/obj/machinery/hypnochair/MouseDrop_T(mob/target, mob/user) + if(user.stat || !Adjacent(user) || !user.Adjacent(target) || !isliving(target) || !user.IsAdvancedToolUser()) + return + if(isliving(user)) + var/mob/living/L = user + if(!(L.mobility_flags & MOBILITY_STAND)) + return + close_machine(target) diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm index b2a35dcf41..421e3433ca 100644 --- a/code/game/machinery/lightswitch.dm +++ b/code/game/machinery/lightswitch.dm @@ -5,6 +5,7 @@ name = "light switch" icon = 'icons/obj/power.dmi' icon_state = "light1" + plane = ABOVE_WALL_PLANE desc = "Make dark." var/on = TRUE var/area/area = null diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index ff79038a96..1887ee46c0 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -679,7 +679,7 @@ /obj/machinery/porta_turret/syndicate/ComponentInitialize() . = ..() - AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) + AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) /obj/machinery/porta_turret/syndicate/energy icon_state = "standard_stun" @@ -788,7 +788,7 @@ /obj/machinery/porta_turret/centcom_shuttle/ComponentInitialize() . = ..() - AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) + AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) /obj/machinery/porta_turret/centcom_shuttle/assess_perp(mob/living/carbon/human/perp) return 0 diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index c26c66a55f..8545e6f35c 100755 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -114,7 +114,6 @@ add_fingerprint(user) if(charging) charging.update_icon() - charging.forceMove(drop_location()) user.put_in_hands(charging) /obj/machinery/recharger/attack_tk(mob/user) diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index 000585a4be..d55faf2343 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -16,6 +16,7 @@ GLOBAL_LIST_EMPTY(allConsoles) desc = "A console intended to send requests to different departments on the station." icon = 'icons/obj/terminals.dmi' icon_state = "req_comp0" + plane = ABOVE_WALL_PLANE var/department = "Unknown" //The list of all departments on the station (Determined from this variable on each unit) Set this to the same thing if you want several consoles in one department var/list/messages = list() //List of all messages var/departmentType = 0 diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index 34db7b0e08..6793d361b5 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -160,10 +160,7 @@ to_chat(user, "You need one length of cable to repair [src]!") return to_chat(user, "You begin to replace the wires...") - if(do_after(user, 30, target = src)) - if(coil.get_amount() < 1) - return - coil.use(1) + if(W.use_tool(src, user, 30, 1)) obj_integrity = max_integrity stat &= ~BROKEN to_chat(user, "You repair \the [src].") diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index f9f4eb3e80..1730569e10 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -115,8 +115,8 @@ return PROCESS_KILL /obj/machinery/space_heater/RefreshParts() - var/laser = 0 - var/cap = 0 + var/laser = 2 + var/cap = 1 for(var/obj/item/stock_parts/micro_laser/M in component_parts) laser += M.rating for(var/obj/item/stock_parts/capacitor/M in component_parts) @@ -166,6 +166,11 @@ else return ..() +/obj/machinery/space_heater/wrench_act(mob/living/user, obj/item/I) + ..() + default_unfasten_wrench(user, I, 5) + return TRUE + /obj/machinery/space_heater/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index 746c17f225..02bb07b8ed 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -21,6 +21,7 @@ desc = null icon = 'icons/obj/status_display.dmi' icon_state = "frame" + plane = ABOVE_WALL_PLANE density = FALSE use_power = IDLE_POWER_USE idle_power_usage = 10 diff --git a/code/game/machinery/telecomms/broadcasting.dm b/code/game/machinery/telecomms/broadcasting.dm index 4e3e11d1e2..a9b6736f05 100644 --- a/code/game/machinery/telecomms/broadcasting.dm +++ b/code/game/machinery/telecomms/broadcasting.dm @@ -100,7 +100,7 @@ obj/source, // the originating radio frequency, // the frequency the signal is taking place on atom/movable/virtualspeaker/speaker, // representation of the method's speaker - datum/language/language, // the langauge of the message + datum/language/language, // the language of the message message, // the text content of the message spans // the list of spans applied to the message ) diff --git a/code/game/machinery/wishgranter.dm b/code/game/machinery/wishgranter.dm index f618888d98..ee28f118fa 100644 --- a/code/game/machinery/wishgranter.dm +++ b/code/game/machinery/wishgranter.dm @@ -11,9 +11,6 @@ var/insisting = 0 /obj/machinery/wish_granter/attack_hand(mob/living/carbon/user) - . = ..() - if(.) - return if(charges <= 0) to_chat(user, "The Wish Granter lies silent.") return @@ -22,22 +19,116 @@ to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.") return - else if(is_special_character(user)) - to_chat(user, "Even to a heart as dark as yours, you know nothing good will come of this. Something instinctual makes you pull away.") - else if (!insisting) to_chat(user, "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?") insisting++ else - to_chat(user, "You speak. [pick("I want the station to disappear","Humanity is corrupt, mankind must be destroyed","I want to be rich", "I want to rule the world","I want immortality.")]. The Wish Granter answers.") - to_chat(user, "Your head pounds for a moment, before your vision clears. You are the avatar of the Wish Granter, and your power is LIMITLESS! And it's all yours. You need to make sure no one can take it from you. No one can know, first.") + if(is_special_character(user)) + to_chat(user, "You speak. [pick("I want power","Humanity is corrupt, mankind must be destroyed", "I want to rule the world","I want immortality")]. The Wish Granter answers.") + to_chat(user, "Your head pounds for a moment, before your vision clears. The Wish Granter, sensing the darkness in your heart, has given you limitless power, and it's all yours!") + user.dna.add_mutation(HULK) + user.dna.add_mutation(XRAY) + user.dna.add_mutation(SPACEMUT) + user.dna.add_mutation(TK) + user.next_move_modifier *= 0.5 //half the delay between attacks! + to_chat(user, "Things around you feel slower!") + charges-- + insisting = FALSE + to_chat(user, "You have a very great feeling about this!") + else + to_chat(user, "The Wish Granter awaits your wish.") + var/wish = input("You want...","Wish") as null|anything in list("Power","Wealth","The Station To Disappear","To Kill","Nothing") + switch(wish) + if("Power") //Gives infinite power in exchange for infinite power going off in your face! + if(charges <= 0) + return + to_chat(user, "Your wish is granted, but at a terrible cost...") + to_chat(user, "The Wish Granter punishes you for your selfishness, warping itself into a delaminating supermatter shard!") + var/obj/item/stock_parts/cell/infinite/powah = new /obj/item/stock_parts/cell/infinite(get_turf(user)) + if(user.put_in_hands(powah)) + to_chat(user, "[powah] materializes into your hands!") + else + to_chat(user, "[powah] materializes onto the floor.") + var/obj/machinery/power/supermatter_crystal/powerwish = new /obj/machinery/power/supermatter_crystal(loc) + powerwish.damage = 700 //right at the emergency threshold + powerwish.produces_gas = FALSE + charges-- + insisting = FALSE + if(!charges) + qdel(src) + if("Wealth") //Gives 1 million space bucks in exchange for being turned into gold! + if(charges <= 0) + return + to_chat(user, "Your wish is granted, but at a cost...") + to_chat(user, "The Wish Granter punishes you for your selfishness, warping your body to match the greed in your heart.") + new /obj/structure/closet/crate/trashcart/moneywish(loc) + new /obj/structure/closet/crate/trashcart/moneywish(loc) + user.set_species(/datum/species/golem/gold) + charges-- + insisting = FALSE + if(!charges) + qdel(src) + if("The Station To Disappear") //teleports you to the station and makes you blind, making the station disappear for you! + if(charges <= 0) + return + to_chat(user, "Your wish is 'granted', but at a terrible cost...") + to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your eyes to match the darkness in your heart.") + user.dna.add_mutation(BLINDMUT) + var/obj/item/organ/eyes/eyes = user.getorganslot(ORGAN_SLOT_EYES) + if(eyes) + eyes.applyOrganDamage(eyes.maxHealth) + var/list/destinations = list() + for(var/obj/item/beacon/B in GLOB.teleportbeacons) + var/turf/T = get_turf(B) + if(is_station_level(T.z)) + destinations += B + var/chosen_beacon = pick(destinations) + var/obj/effect/portal/jaunt_tunnel/J = new (get_turf(src), src, 100, null, FALSE, get_turf(chosen_beacon)) + try_move_adjacent(J) + playsound(src,'sound/effects/sparks4.ogg',50,1) + charges-- + insisting = FALSE + if(!charges) + qdel(src) + if("To Kill") //Makes you kill things in exchange for rewards! + if(charges <= 0) + return + to_chat(user, "Your wish is granted, but at a terrible cost...") + to_chat(user, "The Wish Granter punishes you for your wickedness, warping itself into a dastardly creature for you to kill! ...but it almost seems to reward you for this.") + var/obj/item/melee/transforming/energy/sword/cx/killreward = new /obj/item/melee/transforming/energy/sword/cx(get_turf(user)) + if(user.put_in_hands(killreward)) + to_chat(user, "[killreward] materializes into your hands!") + else + to_chat(user, "[killreward] materializes onto the floor.") + user.next_move_modifier *= 0.8 //20% less delay between attacks! + to_chat(user, "Things around you feel slightly slower!") + var/mob/living/simple_animal/hostile/venus_human_trap/killwish = new /mob/living/simple_animal/hostile/venus_human_trap(loc) + killwish.maxHealth = 1500 + killwish.health = killwish.maxHealth + killwish.vine_grab_distance = 6 + killwish.melee_damage_upper = 30 + killwish.loot = list(/obj/item/twohanded/dualsaber/hypereutactic) + charges-- + insisting = FALSE + if(!charges) + qdel(src) + if("Nothing") //Makes the wish granter disappear + if(charges <= 0) + return + to_chat(user, "The Wish Granter vanishes from sight!") + to_chat(user, "You feel as if you just narrowly avoided a terrible fate...") + charges-- + insisting = FALSE + qdel(src) - charges-- - insisting = 0 +//ITEMS THAT IT USES - user.mind.add_antag_datum(/datum/antagonist/wishgranter) +/obj/structure/closet/crate/trashcart/moneywish + desc = "A heavy, metal trashcart with wheels. Filled with cash." + name = "loaded trash cart" - to_chat(user, "You have a very bad feeling about this.") - - return +/obj/structure/closet/crate/trashcart/moneywish/PopulateContents() //25*20*1000=500,000 + for(var/i in 1 to 25) + var/obj/item/stack/spacecash/c1000/lodsamoney = new /obj/item/stack/spacecash/c1000(src) + lodsamoney.amount = lodsamoney.max_amount diff --git a/code/game/mecha/combat/neovgre.dm b/code/game/mecha/combat/neovgre.dm index c678912a21..fdcc4df151 100644 --- a/code/game/mecha/combat/neovgre.dm +++ b/code/game/mecha/combat/neovgre.dm @@ -62,18 +62,21 @@ /obj/mecha/combat/neovgre/process() ..() - if(GLOB.ratvar_awakens) // At this point only timley intervention by lord singulo could hople to stop the superweapon + if(GLOB.ratvar_awakens) // At this point only timley intervention by lord singulo could hope to stop the superweapon cell.charge = INFINITY max_integrity = INFINITY obj_integrity = max_integrity CHECK_TICK //Just to be on the safe side lag wise - else if(cell.charge < cell.maxcharge) - for(var/obj/effect/clockwork/sigil/transmission/T in range(SIGIL_ACCESS_RANGE, src)) - var/delta = min(recharge_rate, cell.maxcharge - cell.charge) - if (get_clockwork_power() <= delta) - cell.charge += delta - adjust_clockwork_power(-delta) - CHECK_TICK + else + if(cell.charge < cell.maxcharge) + for(var/obj/effect/clockwork/sigil/transmission/T in range(SIGIL_ACCESS_RANGE, src)) + var/delta = min(recharge_rate, cell.maxcharge - cell.charge) + if (get_clockwork_power() >= delta) + cell.charge += delta + adjust_clockwork_power(-delta) + if(obj_integrity < max_integrity && istype(loc, /turf/open/floor/clockwork)) + obj_integrity += min(max_integrity - obj_integrity, max_integrity / 200) + CHECK_TICK /obj/mecha/combat/neovgre/Initialize() .=..() @@ -90,7 +93,7 @@ energy_drain = 30 name = "Aribter Laser Cannon" desc = "Please re-attach this to neovgre and stop asking questions about why it looks like a normal Nanotrasen issue Solaris laser cannon - Nezbere" - fire_sound = "sound/weapons/neovgre_laser.ogg" + fire_sound = 'sound/weapons/neovgre_laser.ogg' /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy/neovgre/can_attach(obj/mecha/combat/neovgre/M) if(istype(M)) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 02115d3e30..32be825489 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -23,11 +23,11 @@ layer = BELOW_MOB_LAYER//icon draw layer infra_luminosity = 15 //byond implementation is bugged. force = 5 - flags_1 = HEAR_1 + flags_1 = HEAR_1|BLOCK_FACE_ATOM_1 var/can_move = 0 //time of next allowed movement - var/mob/living/carbon/occupant = null + var/mob/living/occupant = null var/step_in = 10 //make a step in step_in/10 sec. - var/dir_in = 2//What direction will the mech face when entered/powered on? Defaults to South. + var/dir_in = SOUTH //What direction will the mech face when entered/powered on? Defaults to South. var/normal_step_energy_drain = 10 //How much energy the mech will consume each time it moves. This variable is a backup for when leg actuators affect the energy drain. var/step_energy_drain = 10 var/melee_energy_drain = 15 @@ -495,6 +495,10 @@ occupant_message("Air port connection teared off!") mecha_log_message("Lost connection to gas port.") +/obj/mecha/setDir(newdir) + . = ..() + occupant?.setDir(newdir) + /obj/mecha/Process_Spacemove(var/movement_dir = 0) . = ..() if(.) diff --git a/code/game/mecha/mecha_construction_paths.dm b/code/game/mecha/mecha_construction_paths.dm index de1c035000..19b6d0a9bd 100644 --- a/code/game/mecha/mecha_construction_paths.dm +++ b/code/game/mecha/mecha_construction_paths.dm @@ -3,6 +3,46 @@ //////////////////////////////// /datum/component/construction/mecha var/base_icon + var/looky_helpy = TRUE + +/datum/component/construction/mecha/examine(mob/user) + . = ..() + if(looky_helpy) + switch(steps[index]["key"]) + if(TOOL_WRENCH) + . += "The mech could be wrenched into place." + if(TOOL_SCREWDRIVER) + . += "The mech could be screwed into place." + if(TOOL_WIRECUTTER) + . += "The mech wires could be trimmed into place." + if(/obj/item/stack/cable_coil) + . += "The mech could use some wiring." + if(/obj/item/circuitboard) + . += "The mech could use a type ofcircuitboard." + if(/obj/item/stock_parts/scanning_module) + . += "The mech could use a scanning stock part." + if(/obj/item/stock_parts/capacitor) + . += "The mech could use a power based stock part." + if(/obj/item/stock_parts/cell) + . += "The mech could use a power source." + if(/obj/item/stack/sheet/metal) + . += "The mech could use some sheets of metal." + if(/obj/item/stack/sheet/plasteel) + . += "The mech could use some sheets of strong steel." + if(/obj/item/bikehorn) + . += "HONK IT!." + if(/obj/item/clothing/mask/gas/clown_hat) + . += "GIVE IT CLOWN MAKEUP HONK!." + if(/obj/item/clothing/shoes/clown_shoes) + . += "GIVE IT GOOFY SHOES HONK HONK!." + if(/obj/item/mecha_parts/part) + . += "The mech could use a mech part." + if(/obj/item/stack/ore/bluespace_crystal) + . += "The mech could use a crystal of sorts." + if(/obj/item/assembly/signaler/anomaly) + . += "The mech could use a anomaly of sorts." + else + return /datum/component/construction/mecha/spawn_result() if(!result) diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm index 581283d339..1fe7f74dec 100644 --- a/code/game/mecha/mecha_defense.dm +++ b/code/game/mecha/mecha_defense.dm @@ -77,7 +77,7 @@ /obj/mecha/attack_animal(mob/living/simple_animal/user) mecha_log_message("Attack by simple animal. Attacker - [user].", color="red") if(!user.melee_damage_upper && !user.obj_damage) - user.emote("custom", message = "[user.friendly] [src].") + user.emote("custom", message = "[user.friendly_verb_continuous] [src].") return 0 else var/play_soundeffect = 1 @@ -220,8 +220,7 @@ return else if(istype(W, /obj/item/stack/cable_coil)) if(state == 3 && (internal_damage & MECHA_INT_SHORT_CIRCUIT)) - var/obj/item/stack/cable_coil/CC = W - if(CC.use(2)) + if(W.use_tool(src, user, 0, 2)) clearInternalDamage(MECHA_INT_SHORT_CIRCUIT) to_chat(user, "You replace the fused wires.") else diff --git a/code/game/mecha/mecha_topic.dm b/code/game/mecha/mecha_topic.dm index 8d6328cf08..b1ab944b49 100644 --- a/code/game/mecha/mecha_topic.dm +++ b/code/game/mecha/mecha_topic.dm @@ -333,10 +333,13 @@ send_byjax(occupant,"exosuit.browser","t_port_connection","[internal_tank.connected_port?"Disconnect from":"Connect to"] gas port") if(href_list["dna_lock"]) - if(occupant && !iscarbon(occupant)) - to_chat(occupant, " You do not have any DNA!") + if(!occupant) return - dna_lock = occupant.dna.unique_enzymes + var/mob/living/carbon/C = occupant + if(!istype(C) || !C.dna) + to_chat(C, " You do not have any DNA!") + return + dna_lock = C.dna.unique_enzymes occupant_message("You feel a prick as the needle takes your DNA sample.") if(href_list["reset_dna"]) diff --git a/code/game/objects/effects/contraband.dm b/code/game/objects/effects/contraband.dm index 6b61eb2ebd..69aa3fb654 100644 --- a/code/game/objects/effects/contraband.dm +++ b/code/game/objects/effects/contraband.dm @@ -49,6 +49,7 @@ var/original_name desc = "A large piece of space-resistant printed paper." icon = 'icons/obj/contraband.dmi' + plane = ABOVE_WALL_PLANE anchored = TRUE var/ruined = FALSE var/random_basetype diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index 910c4f4609..e06c172519 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -133,7 +133,7 @@ if(reagents) for(var/datum/reagent/consumable/R in reagents.reagent_list) if(R.nutriment_factor > 0) - H.nutrition += R.nutriment_factor * R.volume + H.adjust_nutrition(R.nutriment_factor * R.volume) reagents.del_reagent(R.type) reagents.trans_to(H, reagents.total_volume) qdel(src) diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index 955b9935dd..8cfdad0432 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -3,7 +3,7 @@ desc = "Graffiti. Damn kids." icon = 'icons/effects/crayondecal.dmi' icon_state = "rune1" - plane = GAME_PLANE //makes the graffiti visible over a wall. + plane = ABOVE_WALL_PLANE //makes the graffiti visible over a wall. gender = NEUTER mergeable_decal = FALSE var/do_icon_rotate = TRUE diff --git a/code/game/objects/effects/decals/decal.dm b/code/game/objects/effects/decals/decal.dm index 3e7706282a..5dbd18aa0c 100644 --- a/code/game/objects/effects/decals/decal.dm +++ b/code/game/objects/effects/decals/decal.dm @@ -35,6 +35,7 @@ icon = 'icons/turf/decals.dmi' icon_state = "warningline" layer = TURF_DECAL_LAYER + plane = ABOVE_WALL_PLANE /obj/effect/turf_decal/Initialize() ..() diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 992e9c84a7..6910bb1db0 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -469,6 +469,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player) /obj/effect/landmark/stationroom var/list/templates = list() layer = BULLET_HOLE_LAYER + plane = ABOVE_WALL_PLANE /obj/effect/landmark/stationroom/New() ..() diff --git a/code/game/objects/effects/spawners/structure.dm b/code/game/objects/effects/spawners/structure.dm index cdf3f3e6b4..7a151c4312 100644 --- a/code/game/objects/effects/spawners/structure.dm +++ b/code/game/objects/effects/spawners/structure.dm @@ -24,6 +24,23 @@ again. name = "window spawner" spawn_list = list(/obj/structure/grille, /obj/structure/window/fulltile) dir = SOUTH + var/electrochromatic + var/electrochromatic_id + +/obj/effect/spawner/structure/window/Initialize() + . = ..() + if(!electrochromatic) + return + if(!electrochromatic_id) + stack_trace("Electrochromatic window spawner set without electromatic id.") + return + if(electrochromatic_id[1] == "!") + electrochromatic_id = SSmapping.get_obfuscated_id(electrochromatic_id) + for(var/obj/structure/window/W in get_turf(src)) + W.electrochromatic_id = electrochromatic_id + W.make_electrochromatic() + if(electrochromatic == ELECTROCHROMATIC_DIMMED) + W.electrochromatic_dim() /obj/effect/spawner/structure/window/hollow name = "hollow window spawner" @@ -140,13 +157,16 @@ again. spawn_list = list(/obj/structure/grille, /obj/structure/window/reinforced/spawner/north, /obj/structure/window/reinforced/spawner/west) . = ..() -//tinted +//tinted and electrochromatic /obj/effect/spawner/structure/window/reinforced/tinted name = "tinted reinforced window spawner" icon_state = "twindow_spawner" spawn_list = list(/obj/structure/grille, /obj/structure/window/reinforced/tinted/fulltile) +/obj/effect/spawner/structure/window/reinforced/tinted/electrochromatic + name = "electrochromatic reinforced window spawner" + electrochromatic = ELECTROCHROMATIC_DIMMED //shuttle window diff --git a/code/game/objects/empulse.dm b/code/game/objects/empulse.dm index d9f231b318..b63a126c5d 100644 --- a/code/game/objects/empulse.dm +++ b/code/game/objects/empulse.dm @@ -7,7 +7,7 @@ if(log) message_admins("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ") - log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ") + log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ") if(heavy_range >= 1) new /obj/effect/temp_visual/emp/pulse(epicenter) @@ -29,4 +29,4 @@ T.emp_act(EMP_LIGHT) else if(distance <= light_range) T.emp_act(EMP_LIGHT) - return 1 \ No newline at end of file + return 1 diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index cb4e7b2a75..76c282e14d 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -139,6 +139,12 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) */ var/datum/block_parry_data/block_parry_data + ///Skills vars + //list of skill PATHS exercised when using this item. An associated bitfield can be set to indicate additional ways the skill is used by this specific item. + var/list/datum/skill/used_skills + var/skill_difficulty = THRESHOLD_UNTRAINED //how difficult it's to use this item in general. + var/skill_gain = DEF_SKILL_GAIN //base skill value gain from using this item. + /obj/item/Initialize() if (attack_verb) @@ -785,14 +791,17 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) var/user = usr tip_timer = addtimer(CALLBACK(src, .proc/openTip, location, control, params, user), timedelay, TIMER_STOPPABLE)//timer takes delay in deciseconds, but the pref is in milliseconds. dividing by 100 converts it. -/obj/item/MouseExited() +/obj/item/MouseExited(location,control,params) + SEND_SIGNAL(src, COMSIG_ITEM_MOUSE_EXIT, location, control, params) deltimer(tip_timer)//delete any in-progress timer if the mouse is moved off the item before it finishes closeToolTip(usr) +/obj/item/MouseEntered(location,control,params) + SEND_SIGNAL(src, COMSIG_ITEM_MOUSE_ENTER, location, control, params) // Called when a mob tries to use the item as a tool. // Handles most checks. -/obj/item/proc/use_tool(atom/target, mob/living/user, delay, amount=0, volume=0, datum/callback/extra_checks) +/obj/item/proc/use_tool(atom/target, mob/living/user, delay, amount=0, volume=0, datum/callback/extra_checks, skill_gain_mult = 1, max_level = INFINITY) // No delay means there is no start message, and no reason to call tool_start_check before use_tool. // Run the start check here so we wouldn't have to call it manually. if(!delay && !tool_start_check(user, amount)) @@ -804,6 +813,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) play_tool_sound(target, volume) if(delay) + if(user.mind && used_skills) + delay = user.mind.item_action_skills_mod(src, delay, skill_difficulty, SKILL_USE_TOOL, null, FALSE) + // Create a callback with checks that would be called every tick by do_after. var/datum/callback/tool_check = CALLBACK(src, .proc/tool_check_callback, user, amount, extra_checks) @@ -828,6 +840,14 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) if(delay >= MIN_TOOL_SOUND_DELAY) play_tool_sound(target, volume) + + if(user.mind && used_skills && skill_gain_mult) + var/gain = skill_gain + delay/SKILL_GAIN_DELAY_DIVISOR + for(var/skill in used_skills) + if(!(SKILL_TRAINING_TOOL in used_skills[skill])) + continue + user.mind.auto_gain_experience(skill, gain*skill_gain_mult, GET_STANDARD_LVL(max_level)) + return TRUE // Called before use_tool if there is a delay, or by use_tool if there isn't. diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm index d248556a9c..5d9c6ee267 100644 --- a/code/game/objects/items/RCD.dm +++ b/code/game/objects/items/RCD.dm @@ -143,8 +143,8 @@ RLD //if user can't be seen from A (only checks surroundings' opaqueness) and can't see A. //jarring, but it should stop people from targetting atoms they can't see... //excluding darkness, to allow RLD to be used to light pitch black dark areas. - if(!((user in view(view_range, A)) || (user in viewers(view_range, A)))) - to_chat(user, "You focus, pointing \the [src] at whatever outside your field of vision in the given direction... to no avail.") + if(!((user in view(view_range, A)) || (user in fov_viewers(view_range, A)))) + to_chat(user, "You focus, pointing \the [src] at whatever outside your field of vision in that direction... to no avail.") return FALSE return TRUE @@ -154,6 +154,7 @@ RLD icon_state = "rcd" lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' + custom_price = 900 max_matter = 160 item_flags = NO_MAT_REDEMPTION | NOBLUDGEON has_ammobar = TRUE @@ -744,7 +745,7 @@ RLD if(istype(A, /obj/machinery/light/)) if(checkResource(deconcost, user)) to_chat(user, "You start deconstructing [A]...") - user.Beam(A,icon_state="nzcrentrs_power",time=15) + user.Beam(A,icon_state="light_beam",time=15) playsound(src.loc, 'sound/machines/click.ogg', 50, 1) if(do_after(user, decondelay, target = A)) if(!useResource(deconcost, user)) @@ -758,7 +759,7 @@ RLD var/turf/closed/wall/W = A if(checkResource(floorcost, user)) to_chat(user, "You start building a wall light...") - user.Beam(A,icon_state="nzcrentrs_power",time=15) + user.Beam(A,icon_state="light_beam",time=15) playsound(src.loc, 'sound/machines/click.ogg', 50, 1) playsound(src.loc, 'sound/effects/light_flicker.ogg', 50, 0) if(do_after(user, floordelay, target = A)) @@ -804,7 +805,7 @@ RLD var/turf/open/floor/F = A if(checkResource(floorcost, user)) to_chat(user, "You start building a floor light...") - user.Beam(A,icon_state="nzcrentrs_power",time=15) + user.Beam(A,icon_state="light_beam",time=15) playsound(src.loc, 'sound/machines/click.ogg', 50, 1) playsound(src.loc, 'sound/effects/light_flicker.ogg', 50, 1) if(do_after(user, floordelay, target = A)) @@ -833,6 +834,12 @@ RLD return TRUE return FALSE +/obj/item/construction/rld/mini + name = "mini-rapid-light-device (MRLD)" + desc = "A device used to rapidly provide lighting sources to an area. Reload with metal, plasteel, glass or compressed matter cartridges." + matter = 100 + max_matter = 100 + /obj/item/rcd_upgrade name = "RCD advanced design disk" desc = "It seems to be empty." diff --git a/code/game/objects/items/RSF.dm b/code/game/objects/items/RSF.dm index ba0766de00..01b351edd0 100644 --- a/code/game/objects/items/RSF.dm +++ b/code/game/objects/items/RSF.dm @@ -7,7 +7,7 @@ RSF name = "\improper Rapid-Service-Fabricator" desc = "A device used to rapidly deploy service items." icon = 'icons/obj/tools.dmi' - icon_state = "rcd" + icon_state = "rsf" lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' opacity = 0 @@ -41,24 +41,21 @@ RSF /obj/item/rsf/attack_self(mob/user) playsound(src.loc, 'sound/effects/pop.ogg', 50, 0) switch(mode) + if(5) + mode = 1 + to_chat(user, "Changed dispensing mode to 'Drinking Glass'") if(1) mode = 2 - to_chat(user, "Changed dispensing mode to 'Drinking Glass'") + to_chat(user, "Changed dispensing mode to 'Paper'") if(2) mode = 3 - to_chat(user, "Changed dispensing mode to 'Paper'") + to_chat(user, "Changed dispensing mode to 'Pen'") if(3) mode = 4 - to_chat(user, "Changed dispensing mode to 'Pen'") + to_chat(user, "Changed dispensing mode to 'Dice Pack'") if(4) mode = 5 - to_chat(user, "Changed dispensing mode to 'Dice Pack'") - if(5) - mode = 6 to_chat(user, "Changed dispensing mode to 'Cigarette'") - if(6) - mode = 1 - to_chat(user, "Changed dispensing mode to 'Dosh'") // Change mode /obj/item/rsf/afterattack(atom/A, mob/user, proximity) @@ -81,26 +78,22 @@ RSF playsound(src.loc, 'sound/machines/click.ogg', 10, 1) switch(mode) if(1) - to_chat(user, "Dispensing Dosh...") - new /obj/item/stack/spacecash/c10(T) - use_matter(200, user) - if(2) to_chat(user, "Dispensing Drinking Glass...") new /obj/item/reagent_containers/food/drinks/drinkingglass(T) use_matter(20, user) - if(3) + if(2) to_chat(user, "Dispensing Paper Sheet...") new /obj/item/paper(T) use_matter(10, user) - if(4) + if(3) to_chat(user, "Dispensing Pen...") new /obj/item/pen(T) use_matter(50, user) - if(5) + if(4) to_chat(user, "Dispensing Dice Pack...") new /obj/item/storage/pill_bottle/dice(T) use_matter(200, user) - if(6) + if(5) to_chat(user, "Dispensing Cigarette...") new /obj/item/clothing/mask/cigarette(T) use_matter(10, user) @@ -117,7 +110,7 @@ RSF name = "Cookie Synthesizer" desc = "A self-recharging device used to rapidly deploy cookies." icon = 'icons/obj/tools.dmi' - icon_state = "rcd" + icon_state = "rsf" lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' var/matter = 10 diff --git a/code/game/objects/items/airlock_painter.dm b/code/game/objects/items/airlock_painter.dm index 45fea91e49..b6be778456 100644 --- a/code/game/objects/items/airlock_painter.dm +++ b/code/game/objects/items/airlock_painter.dm @@ -125,3 +125,112 @@ user.put_in_hands(ink) to_chat(user, "You remove [ink] from [src].") ink = null + + +/obj/item/airlock_painter/decal + name = "decal painter" + desc = "An airlock painter, reprogramed to use a different style of paint in order to apply decals for floor tiles as well, in addition to repainting doors. Decals break when the floor tiles are removed. Alt-Click to change design." + icon = 'icons/obj/objects.dmi' + icon_state = "decal_sprayer" + item_state = "decalsprayer" + custom_materials = list(/datum/material/iron=2000, /datum/material/glass=500) + var/stored_dir = 2 + var/stored_color = "" + var/stored_decal = "warningline" + var/stored_decal_total = "warningline" + var/color_list = list("","red","white") + var/dir_list = list(1,2,4,8) + var/decal_list = list(list("Warning Line","warningline"), + list("Warning Line Corner","warninglinecorner"), + list("Caution Label","caution"), + list("Directional Arrows","arrows"), + list("Stand Clear Label","stand_clear"), + list("Box","box"), + list("Box Corner","box_corners"), + list("Delivery Marker","delivery"), + list("Warning Box","warn_full")) + +/obj/item/airlock_painter/decal/afterattack(atom/target, mob/user, proximity) + . = ..() + var/turf/open/floor/F = target + if(!proximity) + to_chat(user, "You need to get closer!") + return + if(use_paint(user) && isturf(F)) + F.AddComponent(/datum/component/decal, 'icons/turf/decals.dmi', stored_decal_total, stored_dir, CLEAN_STRONG, color, null, null, alpha) + +/obj/item/airlock_painter/decal/attack_self(mob/user) + if((ink) && (ink.charges >= 1)) + to_chat(user, "[src] beeps to prevent you from removing the toner until out of charges.") + return + . = ..() + +/obj/item/airlock_painter/decal/AltClick(mob/user) + . = ..() + ui_interact(user) + +/obj/item/airlock_painter/decal/Initialize() + . = ..() + ink = new /obj/item/toner/large(src) + +/obj/item/airlock_painter/decal/proc/update_decal_path() + var/yellow_fix = "" //This will have to do until someone refactor's markings.dm + if (stored_color) + yellow_fix = "_" + stored_decal_total = "[stored_decal][yellow_fix][stored_color]" + return + +/obj/item/airlock_painter/decal/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "decal_painter", name, 500, 400, master_ui, state) + ui.open() + +/obj/item/airlock_painter/decal/ui_data(mob/user) + var/list/data = list() + data["decal_direction"] = stored_dir + data["decal_color"] = stored_color + data["decal_style"] = stored_decal + data["decal_list"] = list() + data["color_list"] = list() + data["dir_list"] = list() + + for(var/i in decal_list) + data["decal_list"] += list(list( + "name" = i[1], + "decal" = i[2] + )) + for(var/j in color_list) + data["color_list"] += list(list( + "colors" = j + )) + for(var/k in dir_list) + data["dir_list"] += list(list( + "dirs" = k + )) + return data + +/obj/item/airlock_painter/decal/ui_act(action,list/params) + if(..()) + return + switch(action) + //Lists of decals and designs + if("select decal") + var/selected_decal = params["decals"] + stored_decal = selected_decal + if("select color") + var/selected_color = params["colors"] + stored_color = selected_color + if("selected direction") + var/selected_direction = text2num(params["dirs"]) + stored_dir = selected_direction + update_decal_path() + . = TRUE + +/obj/item/airlock_painter/decal/debug + name = "extreme decal painter" + icon_state = "decal_sprayer_ex" + +/obj/item/airlock_painter/decal/debug/Initialize() + . = ..() + ink = new /obj/item/toner/extreme(src) \ No newline at end of file diff --git a/code/game/objects/items/apc_frame.dm b/code/game/objects/items/apc_frame.dm index 1f6dff490d..3640db2d8a 100644 --- a/code/game/objects/items/apc_frame.dm +++ b/code/game/objects/items/apc_frame.dm @@ -58,18 +58,22 @@ /obj/item/wallframe/proc/after_attach(var/obj/O) transfer_fingerprints_to(O) -/obj/item/wallframe/attackby(obj/item/W, mob/user, params) - ..() - if(istype(W, /obj/item/screwdriver)) - // For camera-building borgs - var/turf/T = get_step(get_turf(user), user.dir) - if(iswallturf(T)) - T.attackby(src, user, params) +/obj/item/wallframe/screwdriver_act(mob/user, obj/item/I) + . = ..() + if(.) + return + // For camera-building borgs + var/turf/T = get_step(get_turf(user), user.dir) + if(iswallturf(T)) + T.attackby(src, user) +/obj/item/wallframe/wrench_act(mob/user, obj/item/I) + if(!custom_materials) + return var/metal_amt = round(custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)]/MINERAL_MATERIAL_AMOUNT) var/glass_amt = round(custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)]/MINERAL_MATERIAL_AMOUNT) - if(istype(W, /obj/item/wrench) && (metal_amt || glass_amt)) + if(metal_amt || glass_amt) to_chat(user, "You dismantle [src].") if(metal_amt) new /obj/item/stack/sheet/metal(get_turf(src), metal_amt) diff --git a/code/game/objects/items/cardboard_cutouts.dm b/code/game/objects/items/cardboard_cutouts.dm index 2daf6f0c0b..6648db46c4 100644 --- a/code/game/objects/items/cardboard_cutouts.dm +++ b/code/game/objects/items/cardboard_cutouts.dm @@ -6,17 +6,42 @@ icon_state = "cutout_basic" w_class = WEIGHT_CLASS_BULKY resistance_flags = FLAMMABLE - // Possible restyles for the cutout; - // add an entry in change_appearance() if you add to here - var/list/possible_appearances = list("Assistant", "Clown", "Mime", - "Traitor", "Nuke Op", "Cultist", "Brass Cultist", "Clockwork Cultist", - "Revolutionary", "Wizard", "Shadowling", "Xenomorph", "Xenomorph Maid", "Swarmer", - "Ash Walker", "Deathsquad Officer", "Ian", "Slaughter Demon", - "Laughter Demon", "Private Security Officer", "Securitron", "Gondola", "Monkey") - var/pushed_over = FALSE //If the cutout is pushed over and has to be righted - var/deceptive = FALSE //If the cutout actually appears as what it portray and not a discolored version + /// Possible restyles for the cutout, add an entry in change_appearance() if you add to here + var/static/list/possible_appearances + /// If the cutout is pushed over and has to be righted + var/pushed_over = FALSE + /// If the cutout actually appears as what it portray and not a discolored version + var/deceptive = FALSE - var/lastattacker = null +/obj/item/cardboard_cutout/Initialize() + . = ..() + if(possible_appearances) + return + possible_appearances = sortList(list( + "Assistant" = image(icon = src.icon, icon_state = "cutout_greytide"), + "Clown" = image(icon = src.icon, icon_state = "cutout_clown"), + "Mime" = image(icon = src.icon, icon_state = "cutout_mime"), + "Traitor" = image(icon = src.icon, icon_state = "cutout_traitor"), + "Nuke Op" = image(icon = src.icon, icon_state = "cutout_fluke"), + "Cultist" = image(icon = src.icon, icon_state = "cutout_cultist"), + "Brass Cultist" = image(icon = src.icon, icon_state = "cutout_servant"), + "Clockwork Cultist" = image(icon = src.icon, icon_state = "cutout_new_servant"), + "Revolutionary" = image(icon = src.icon, icon_state = "cutout_viva"), + "Wizard" = image(icon = src.icon, icon_state = "cutout_wizard"), + "Shadowling" = image(icon = src.icon, icon_state = "cutout_shadowling"), + "Xenomorph" = image(icon = src.icon, icon_state = "cutout_fukken_xeno"), + "Xenomorph Maid" = image(icon = src.icon, icon_state = "cutout_lusty"), + "Swarmer" = image(icon = src.icon, icon_state = "cutout_swarmer"), + "Ash Walker" = image(icon = src.icon, icon_state = "cutout_free_antag"), + "Deathsquad Officer" = image(icon = src.icon, icon_state = "cutout_deathsquad"), + "Ian" = image(icon = src.icon, icon_state = "cutout_ian"), + "Slaughter Demon" = image(icon = 'icons/mob/mob.dmi', icon_state = "daemon"), + "Laughter Demon" = image(icon = 'icons/mob/mob.dmi', icon_state = "bowmon"), + "Private Security Officer" = image(icon = src.icon, icon_state = "cutout_ntsec"), + "Securitron" = image(icon = src.icon, icon_state = "cutout_law"), + "Gondola" = image(icon = src.icon, icon_state = "cutout_gondola"), + "Monkey" = image(icon = src.icon, icon_state = "cutout_monky"), + )) //ATTACK HAND IGNORING PARENT RETURN VALUE /obj/item/cardboard_cutout/attack_hand(mob/living/user) @@ -76,22 +101,21 @@ push_over() return BULLET_ACT_HIT +/** + * change_appearance: Changes a skin of the cardboard cutout based on a user's choice + * + * Arguments: + * * crayon The crayon used to change and recolor the cardboard cutout + * * user The mob choosing a skin of the cardboard cutout + */ /obj/item/cardboard_cutout/proc/change_appearance(obj/item/toy/crayon/crayon, mob/living/user) - if(!crayon || !user) - return - if(pushed_over) - to_chat(user, "Right [src] first!") - return - if(crayon.check_empty(user)) - return - if(crayon.is_capped) - to_chat(user, "Take the cap off first!") - return - var/new_appearance = input(user, "Choose a new appearance for [src].", "26th Century Deception") as null|anything in possible_appearances - if(!new_appearance || !crayon || !user.canUseTopic(src)) + var/new_appearance = show_radial_menu(user, src, possible_appearances, custom_check = CALLBACK(src, .proc/check_menu, user, crayon), radius = 36, require_near = TRUE) + if(!new_appearance) return if(!do_after(user, 10, FALSE, src, TRUE)) - return + return FALSE + if(!check_menu(user, crayon)) + return FALSE user.visible_message("[user] gives [src] a new look.", "Voila! You give [src] a new look.") crayon.use_charges(1) crayon.check_empty(user) @@ -196,7 +220,33 @@ name = "monkey ([rand(1, 999)])" desc = "A cardboard cutout of a monkey." icon_state = "cutout_monky" - return 1 + else + return FALSE + return TRUE + +/** + * check_menu: Checks if we are allowed to interact with a radial menu + * + * Arguments: + * * user The mob interacting with a menu + * * crayon The crayon used to interact with a menu + */ +/obj/item/cardboard_cutout/proc/check_menu(mob/living/user, obj/item/toy/crayon/crayon) + if(!istype(user)) + return FALSE + if(user.incapacitated()) + return FALSE + if(pushed_over) + to_chat(user, "Right [src] first!") + return FALSE + if(!crayon || !user.is_holding(crayon)) + return FALSE + if(crayon.check_empty(user)) + return FALSE + if(crayon.is_capped) + to_chat(user, "Take the cap off first!") + return FALSE + return TRUE /obj/item/cardboard_cutout/setDir(newdir) dir = SOUTH diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index c23bc2bd5b..7036a78bc4 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -6,8 +6,6 @@ * FINGERPRINT CARD */ - - /* * DATA CARDS - Used for the IC data card reader */ @@ -173,13 +171,22 @@ var/registered_name = null // The name registered_name on the card var/assignment = null var/access_txt // mapping aid - - + var/bank_support = ID_FREE_BANK_ACCOUNT + var/datum/bank_account/registered_account + var/obj/machinery/paystand/my_store /obj/item/card/id/Initialize(mapload) . = ..() if(mapload && access_txt) access = text2access(access_txt) + switch(bank_support) + if(ID_FREE_BANK_ACCOUNT) + var/turf/T = get_turf(src) + if(T && is_vr_level(T.z)) //economy is exploitable on VR in so many ways. + bank_support = ID_NO_BANK_ACCOUNT + if(ID_LOCKED_BANK_ACCOUNT) + registered_account = new /datum/bank_account/remote/non_transferable(pick(GLOB.redacted_strings)) + /obj/item/card/id/vv_edit_var(var_name, var_value) . = ..() @@ -193,12 +200,149 @@ user.visible_message("[user] shows you: [icon2html(src, viewers(user))] [src.name].", \ "You show \the [src.name].") add_fingerprint(user) + +/obj/item/card/id/attackby(obj/item/W, mob/user, params) + if(!bank_support) + return ..() + if(istype(W, /obj/item/holochip)) + insert_money(W, user) + else if(istype(W, /obj/item/stack/spacecash) || istype(W, /obj/item/coin)) + insert_money(W, user, TRUE) + else if(istype(W, /obj/item/storage/bag/money)) + var/obj/item/storage/bag/money/money_bag = W + var/list/money_contained = money_bag.contents + var/money_added = mass_insert_money(money_contained, user) + if (money_added) + to_chat(user, "You stuff the contents into the card! They disappear in a puff of bluespace smoke, adding [money_added] worth of credits to the linked account.") + else + return ..() + +/obj/item/card/id/proc/insert_money(obj/item/I, mob/user, physical_currency) + var/cash_money = I.get_item_credit_value() + if(!cash_money) + to_chat(user, "[I] doesn't seem to be worth anything!") return + if(!registered_account) + to_chat(user, "[src] doesn't have a linked account to deposit [I] into!") + return + + registered_account.adjust_money(cash_money) + if(physical_currency) + to_chat(user, "You stuff [I] into [src]. It disappears in a small puff of bluespace smoke, adding [cash_money] credits to the linked account.") + else + to_chat(user, "You insert [I] into [src], adding [cash_money] credits to the linked account.") + + to_chat(user, "The linked account now reports a balance of [registered_account.account_balance] cr.") + qdel(I) + +/obj/item/card/id/proc/mass_insert_money(list/money, mob/user) + if (!money || !money.len) + return FALSE + + var/total = 0 + + for (var/obj/item/physical_money in money) + var/cash_money = physical_money.get_item_credit_value() + + total += cash_money + + registered_account.adjust_money(cash_money) + + QDEL_LIST(money) + + return total + +/obj/item/card/id/proc/alt_click_can_use_id(mob/living/user) + if(!isliving(user)) + return + if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + return + + return TRUE + +// Returns true if new account was set. +/obj/item/card/id/proc/set_new_account(mob/living/user) + if(bank_support != ID_FREE_BANK_ACCOUNT) + to_chat(user, "This ID has no modular banking support whatsover, must be an older model...") + return + . = FALSE + var/datum/bank_account/old_account = registered_account + + var/new_bank_id = input(user, "Enter your account ID number.", "Account Reclamation", 111111) as num | null + + if (isnull(new_bank_id)) + return + + if(!alt_click_can_use_id(user)) + return + if(!new_bank_id || new_bank_id < 111111 || new_bank_id > 999999) + to_chat(user, "The account ID number needs to be between 111111 and 999999.") + return + if (registered_account && registered_account.account_id == new_bank_id) + to_chat(user, "The account ID was already assigned to this card.") + return + + for(var/A in SSeconomy.bank_accounts) + var/datum/bank_account/B = A + if(B.account_id == new_bank_id) + if (old_account) + old_account.bank_cards -= src + + B.bank_cards += src + registered_account = B + to_chat(user, "The provided account has been linked to this ID card.") + + return TRUE + + to_chat(user, "The account ID number provided is invalid.") + return + +/obj/item/card/id/AltClick(mob/living/user) + . = ..() + if(!bank_support || !alt_click_can_use_id(user)) + return + + if(!registered_account && bank_support == ID_FREE_BANK_ACCOUNT) + set_new_account(user) + return + + if (world.time < registered_account.withdrawDelay) + registered_account.bank_card_talk("ERROR: UNABLE TO LOGIN DUE TO SCHEDULED MAINTENANCE. MAINTENANCE IS SCHEDULED TO COMPLETE IN [(registered_account.withdrawDelay - world.time)/10] SECONDS.", TRUE) + return + + var/amount_to_remove = input(user, "How much do you want to withdraw? Current Balance: [registered_account.account_balance]", "Withdraw Funds", 5) as num|null + + if(!amount_to_remove || amount_to_remove < 0) + return + if(!alt_click_can_use_id(user)) + return + amount_to_remove = FLOOR(min(amount_to_remove, registered_account.account_balance), 1) + if(amount_to_remove && registered_account.adjust_money(-amount_to_remove)) + var/obj/item/holochip/holochip = new (user.drop_location(), amount_to_remove) + user.put_in_hands(holochip) + to_chat(user, "You withdraw [amount_to_remove] credits into a holochip.") + return + registered_account.bank_card_talk("ERROR: The linked account has no sufficient credits to perform that withdrawal.", TRUE) + /obj/item/card/id/examine(mob/user) . = ..() if(mining_points) . += "There's [mining_points] mining equipment redemption point\s loaded onto this card." + if(!bank_support || (bank_support == ID_LOCKED_BANK_ACCOUNT && !registered_account)) + . += "This ID has no banking support whatsover, must be an older model..." + else if(registered_account) + . += "The account linked to the ID belongs to '[registered_account.account_holder]' and reports a balance of [registered_account.account_balance] cr." + if(registered_account.account_job) + var/datum/bank_account/D = SSeconomy.get_dep_account(registered_account.account_job.paycheck_department) + if(D) + . += "The [D.account_holder] reports a balance of [D.account_balance] cr." + . += "Alt-Click the ID to pull money from the linked account in the form of holochips." + . += "You can insert credits into the linked account by pressing holochips, cash, or coins against the ID." + if(registered_account.account_holder == user.real_name) + . += "If you lose this ID card, you can reclaim your account by Alt-Clicking a blank ID card while holding it and entering your account ID number." + else + . += "There is no registered account linked to this card. Alt-Click to add one." /obj/item/card/id/GetAccess() return access @@ -280,8 +424,12 @@ update_label("John Doe", "Clowny") else return ..() - var/popup_input = alert(user, "Choose Action", "Agent ID", "Show", "Forge/Reset") - if(user.incapacitated()) + var/popup_input + if(bank_support == ID_FREE_BANK_ACCOUNT) + popup_input = alert(user, "Choose Action", "Agent ID", "Show", "Forge/Reset", "Change Account ID") + else + popup_input = alert(user, "Choose Action", "Agent ID", "Show", "Forge/Reset") + if(!user.canUseTopic(src, BE_CLOSE, FALSE)) return if(popup_input == "Forge/Reset" && !forged) var/input_name = stripped_input(user, "What name would you like to put on this card? Leave blank to randomise.", "Agent card name", registered_name ? registered_name : (ishuman(user) ? user.real_name : user.name), MAX_NAME_LEN) @@ -304,6 +452,18 @@ update_label("John Doe", "Clowny") forged = TRUE to_chat(user, "You successfully forge the ID card.") log_game("[key_name(user)] has forged \the [initial(name)] with name \"[registered_name]\" and occupation \"[assignment]\".") + + // First time use automatically sets the account id to the user. + if (first_use && !registered_account) + if(ishuman(user)) + var/mob/living/carbon/human/accountowner = user + + for(var/bank_account in SSeconomy.bank_accounts) + var/datum/bank_account/account = bank_account + if(account.account_id == accountowner.account_id) + account.bank_cards += src + registered_account = account + to_chat(user, "Your account number has been automatically assigned.") return else if (popup_input == "Forge/Reset" && forged) registered_name = initial(registered_name) @@ -313,6 +473,9 @@ update_label("John Doe", "Clowny") forged = FALSE to_chat(user, "You successfully reset the ID card.") return + else if (popup_input == "Change Account ID") + set_new_account(user) + return return ..() /obj/item/card/id/syndicate/anyone @@ -329,6 +492,15 @@ update_label("John Doe", "Clowny") assignment = "Syndicate Overlord" access = list(ACCESS_SYNDICATE) +/obj/item/card/id/no_banking + bank_support = ID_NO_BANK_ACCOUNT + +/obj/item/card/id/locked_banking + bank_support = ID_LOCKED_BANK_ACCOUNT + +/obj/item/card/id/syndicate/locked_banking + bank_support = ID_LOCKED_BANK_ACCOUNT + /obj/item/card/id/captains_spare name = "captain's spare ID" desc = "The spare ID of the High Lord himself." @@ -516,6 +688,34 @@ update_label("John Doe", "Clowny") desc = "A special ID card that allows access to APC terminals." access = list(ACCESS_ENGINE_EQUIP) +/obj/item/card/id/departmental_budget + name = "departmental card (FUCK)" + desc = "Provides access to the departmental budget." + var/department_ID = ACCOUNT_CIV + var/department_name = ACCOUNT_CIV_NAME + +/obj/item/card/id/departmental_budget/Initialize() + . = ..() + var/datum/bank_account/B = SSeconomy.get_dep_account(department_ID) + if(B) + registered_account = B + if(!B.bank_cards.Find(src)) + B.bank_cards += src + name = "departmental card ([department_name])" + desc = "Provides access to the [department_name]." + SSeconomy.dep_cards += src + +/obj/item/card/id/departmental_budget/Destroy() + SSeconomy.dep_cards -= src + return ..() + +/obj/item/card/id/departmental_budget/update_label() + return + +/obj/item/card/id/departmental_budget/car + department_ID = ACCOUNT_CAR + department_name = ACCOUNT_CAR_NAME + //Polychromatic Knight Badge /obj/item/card/id/knight @@ -578,5 +778,5 @@ update_label("John Doe", "Clowny") /obj/item/card/id/debug/Initialize() access = get_all_accesses()+get_all_centcom_access()+get_all_syndicate_access() + registered_account = SSeconomy.get_dep_account(ACCOUNT_CAR) . = ..() - diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 2303278f5c..6ebeffe90f 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -506,6 +506,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM resistance_flags = FIRE_PROOF light_color = LIGHT_COLOR_FIRE grind_results = list(/datum/reagent/iron = 1, /datum/reagent/fuel = 5, /datum/reagent/oil = 5) + custom_price = 55 /obj/item/lighter/Initialize() . = ..() @@ -710,7 +711,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM item_state = "black_vape" w_class = WEIGHT_CLASS_TINY var/chem_volume = 100 - var/vapetime = FALSE //this so it won't puff out clouds every tick + var/vapetime = FALSE //this so it won't puff out clouds every tick var/screw = FALSE // kinky var/super = FALSE //for the fattest vapes dude. diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm index b788c3fcba..b90fd1c1af 100644 --- a/code/game/objects/items/circuitboards/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm @@ -229,10 +229,11 @@ def_components = list(/obj/item/stack/ore/bluespace_crystal = /obj/item/stack/ore/bluespace_crystal/artificial) /obj/item/circuitboard/machine/vendor - name = "Booze-O-Mat Vendor (Machine Board)" + name = "Custom Vendor (Machine Board)" desc = "You can turn the \"brand selection\" dial using a screwdriver." - build_path = /obj/machinery/vending/boozeomat - req_components = list(/obj/item/vending_refill/boozeomat = 1) + custom_premium_price = 100 + build_path = /obj/machinery/vending/custom + req_components = list(/obj/item/vending_refill/custom = 1) var/static/list/vending_names_paths = list( /obj/machinery/vending/boozeomat = "Booze-O-Mat", @@ -269,7 +270,8 @@ /obj/machinery/vending/wardrobe/viro_wardrobe = "ViroDrobe", /obj/machinery/vending/clothing = "ClothesMate", /obj/machinery/vending/medical = "NanoMed Plus", - /obj/machinery/vending/wallmed = "NanoMed") + /obj/machinery/vending/wallmed = "NanoMed", + /obj/machinery/vending/custom = "Custom Vendor") /obj/item/circuitboard/machine/vendor/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/screwdriver)) @@ -690,6 +692,17 @@ def_components = list(/obj/item/stock_parts/cell = /obj/item/stock_parts/cell/high) needs_anchored = FALSE +/obj/item/circuitboard/machine/chem_dispenser/apothecary + name = "Apotechary Chem Dispenser (Machine Board)" + build_path = /obj/machinery/chem_dispenser/apothecary + req_components = list( + /obj/item/stock_parts/matter_bin = 1, + /obj/item/stock_parts/capacitor = 1, + /obj/item/stock_parts/manipulator = 1, + /obj/item/stack/sheet/glass = 1, + /obj/item/stock_parts/cell = 1) + def_components = list(/obj/item/stock_parts/cell = /obj/item/stock_parts/cell/upgraded/plus) + /obj/item/circuitboard/machine/chem_dispenser/drinks name = "Soda Dispenser (Machine Board)" build_path = /obj/machinery/chem_dispenser/drinks @@ -705,6 +718,10 @@ def_components = list(/obj/item/stock_parts/cell = /obj/item/stock_parts/cell/high) needs_anchored = FALSE +/obj/item/circuitboard/machine/sleeper/party + name = "Party Pod (Machine Board)" + build_path = /obj/machinery/sleeper/party + /obj/item/circuitboard/machine/smoke_machine name = "Smoke Machine (Machine Board)" build_path = /obj/machinery/smoke_machine @@ -882,6 +899,16 @@ name = "Departmental Protolathe - Service (Machine Board)" build_path = /obj/machinery/rnd/production/protolathe/department/service +/obj/item/circuitboard/machine/bepis + name = "BEPIS Chamber (Machine Board)" + build_path = /obj/machinery/rnd/bepis + req_components = list( + /obj/item/stack/cable_coil = 5, + /obj/item/stock_parts/capacitor = 1, + /obj/item/stock_parts/manipulator = 1, + /obj/item/stock_parts/micro_laser = 1, + /obj/item/stock_parts/scanning_module = 1) + /obj/item/circuitboard/machine/techfab name = "\improper Techfab (Machine Board)" build_path = /obj/machinery/rnd/production/techfab @@ -1040,6 +1067,11 @@ build_path = /obj/machinery/ore_silo req_components = list() +/obj/item/circuitboard/machine/paystand + name = "Pay Stand (Machine Board)" + build_path = /obj/machinery/paystand + req_components = list() + /obj/item/circuitboard/machine/autobottler name = "Auto-Bottler (Machine Board)" build_path = /obj/machinery/rnd/production/protolathe/department/autobottler //Manips make you print things cheaper, even chems @@ -1061,3 +1093,12 @@ /obj/item/stock_parts/matter_bin = 3, /obj/item/stock_parts/manipulator = 1, /obj/item/stack/sheet/glass = 1) + +/obj/item/circuitboard/machine/hypnochair + name = "Enhanced Interrogation Chamber (Machine Board)" + icon_state = "security" + build_path = /obj/machinery/hypnochair + req_components = list( + /obj/item/stock_parts/micro_laser = 2, + /obj/item/stock_parts/scanning_module = 2 + ) diff --git a/code/game/objects/items/crab17.dm b/code/game/objects/items/crab17.dm new file mode 100644 index 0000000000..8d55d3d5a2 --- /dev/null +++ b/code/game/objects/items/crab17.dm @@ -0,0 +1,229 @@ +/obj/item/suspiciousphone + name = "suspicious phone" + desc = "This device raises pink levels to unknown highs." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "suspiciousphone" + w_class = WEIGHT_CLASS_SMALL + attack_verb = list("dumped") + var/dumped = FALSE + +/obj/item/suspiciousphone/attack_self(mob/user) + if(!ishuman(user)) + to_chat(user, "This device is too advanced for you!") + return + if(dumped) + to_chat(user, "You already activated Protocol CRAB-17.") + return FALSE + if(alert(user, "Are you sure you want to crash this market with no survivors?", "Protocol CRAB-17", "Yes", "No") == "Yes") + if(dumped || QDELETED(src)) //Prevents fuckers from cheesing alert + return FALSE + var/turf/targetturf = get_safe_random_station_turf() + if (!targetturf) + return FALSE + new /obj/effect/dumpeetTarget(targetturf, user) + dumped = TRUE + +/obj/structure/checkoutmachine + name = "\improper Nanotrasen Space-Coin Market" + desc = "This is good for spacecoin because" + icon = 'icons/obj/money_machine.dmi' + icon_state = "bogdanoff" + layer = LARGE_MOB_LAYER + armor = list("melee" = 80, "bullet" = 30, "laser" = 30, "energy" = 60, "bomb" = 90, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 80) + density = TRUE + pixel_z = -8 + max_integrity = 5000 + var/list/accounts_to_rob + var/mob/living/carbon/human/bogdanoff + var/canwalk = FALSE + +/obj/structure/checkoutmachine/examine(mob/living/user) + . = ..() + . += "It's integrated integrity meter reads: HEALTH: [obj_integrity]." + +/obj/structure/checkoutmachine/proc/check_if_finished() + for(var/i in accounts_to_rob) + var/datum/bank_account/B = i + if (B.being_dumped) + return FALSE + return TRUE + +/obj/structure/checkoutmachine/attackby(obj/item/W, mob/user, params) + if(check_if_finished()) + qdel(src) + return + if(istype(W, /obj/item/card/id)) + var/obj/item/card/id/card = W + if(!card.registered_account) + to_chat(user, "This card does not have a registered account!") + return + if(!card.registered_account.being_dumped) + to_chat(user, "It appears that your funds are safe from draining!") + return + if(do_after(user, 40, target = src)) + if(!card.registered_account.being_dumped) + return + to_chat(user, "You quickly cash out your funds to a more secure banking location. Funds are safu.") // This is a reference and not a typo + card.registered_account.being_dumped = FALSE + card.registered_account.withdrawDelay = 0 + if(check_if_finished()) + qdel(src) + return + else + return ..() + +/obj/structure/checkoutmachine/Initialize(mapload, mob/living/user) + . = ..() + bogdanoff = user + add_overlay("flaps") + add_overlay("hatch") + add_overlay("legs_retracted") + addtimer(CALLBACK(src, .proc/startUp), 50) + QDEL_IN(src, 8 MINUTES) //Self destruct after 8 min + + +/obj/structure/checkoutmachine/proc/startUp() //very VERY snowflake code that adds a neat animation when the pod lands. + start_dumping() //The machine doesnt move during this time, giving people close by a small window to grab their funds before it starts running around + sleep(10) + if(QDELETED(src)) + return + playsound(src, 'sound/machines/click.ogg', 15, TRUE, -3) + cut_overlay("flaps") + sleep(10) + if(QDELETED(src)) + return + playsound(src, 'sound/machines/click.ogg', 15, TRUE, -3) + cut_overlay("hatch") + sleep(30) + if(QDELETED(src)) + return + playsound(src,'sound/machines/twobeep.ogg',50,FALSE) + var/mutable_appearance/hologram = mutable_appearance(icon, "hologram") + hologram.pixel_y = 16 + add_overlay(hologram) + var/mutable_appearance/holosign = mutable_appearance(icon, "holosign") + holosign.pixel_y = 16 + add_overlay(holosign) + add_overlay("legs_extending") + cut_overlay("legs_retracted") + pixel_z += 4 + sleep(5) + if(QDELETED(src)) + return + add_overlay("legs_extended") + cut_overlay("legs_extending") + pixel_z += 4 + sleep(20) + if(QDELETED(src)) + return + add_overlay("screen_lines") + sleep(5) + if(QDELETED(src)) + return + cut_overlay("screen_lines") + sleep(5) + if(QDELETED(src)) + return + add_overlay("screen_lines") + add_overlay("screen") + sleep(5) + if(QDELETED(src)) + return + playsound(src,'sound/machines/triple_beep.ogg',50,FALSE) + add_overlay("text") + sleep(10) + if(QDELETED(src)) + return + add_overlay("legs") + cut_overlay("legs_extended") + cut_overlay("screen") + add_overlay("screen") + cut_overlay("screen_lines") + add_overlay("screen_lines") + cut_overlay("text") + add_overlay("text") + canwalk = TRUE + START_PROCESSING(SSfastprocess, src) + +/obj/structure/checkoutmachine/Destroy() + stop_dumping() + STOP_PROCESSING(SSfastprocess, src) + priority_announce("The credit deposit machine at [get_area(src)] has been destroyed. Station funds have stopped draining!", sender_override = "CRAB-17 Protocol") + explosion(src, 0,0,1, flame_range = 2) + return ..() + +/obj/structure/checkoutmachine/proc/start_dumping() + accounts_to_rob = SSeconomy.bank_accounts.Copy() + accounts_to_rob -= bogdanoff.get_bank_account() + for(var/i in accounts_to_rob) + var/datum/bank_account/B = i + B.dumpeet() + dump() + +/obj/structure/checkoutmachine/proc/dump() + var/percentage_lost = (rand(5, 15) / 100) + for(var/i in accounts_to_rob) + var/datum/bank_account/B = i + if(!B.being_dumped) + continue + var/amount = B.account_balance * percentage_lost + var/datum/bank_account/account = bogdanoff.get_bank_account() + if (account) // get_bank_account() may return FALSE + account.transfer_money(B, amount) + B.bank_card_talk("You have lost [percentage_lost * 100]% of your funds! A spacecoin credit deposit machine is located at: [get_area(src)].") + addtimer(CALLBACK(src, .proc/dump), 150) //Drain every 15 seconds + +/obj/structure/checkoutmachine/process() + var/anydir = pick(GLOB.cardinals) + if(Process_Spacemove(anydir)) + Move(get_step(src, anydir), anydir) + +/obj/structure/checkoutmachine/proc/stop_dumping() + for(var/i in accounts_to_rob) + var/datum/bank_account/B = i + B.being_dumped = FALSE + +/obj/effect/dumpeetFall //Falling pod + name = "" + icon = 'icons/obj/money_machine_64.dmi' + pixel_z = 300 + desc = "Get out of the way!" + layer = FLY_LAYER//that wasnt flying, that was falling with style! + icon_state = "missile_blur" + +/obj/effect/dumpeetTarget + name = "Landing Zone Indicator" + desc = "A holographic projection designating the landing zone of something. It's probably best to stand back." + icon = 'icons/mob/actions/actions_items.dmi' + icon_state = "sniper_zoom" + layer = PROJECTILE_HIT_THRESHHOLD_LAYER + light_range = 2 + var/obj/effect/dumpeetFall/DF + var/obj/structure/checkoutmachine/dump + var/mob/living/carbon/human/bogdanoff + +/obj/effect/ex_act() + return + +/obj/effect/dumpeetTarget/Initialize(mapload, user) + . = ..() + bogdanoff = user + addtimer(CALLBACK(src, .proc/startLaunch), 100) + sound_to_playing_players('sound/items/dump_it.ogg', 20) + deadchat_broadcast("Protocol CRAB-17 has been activated. A space-coin market has been launched at the station!", turf_target = get_turf(src)) + +/obj/effect/dumpeetTarget/proc/startLaunch() + DF = new /obj/effect/dumpeetFall(drop_location()) + dump = new /obj/structure/checkoutmachine(null, bogdanoff) + priority_announce("The spacecoin bubble has popped! Get to the credit deposit machine at [get_area(src)] and cash out before you lose all of your funds!", sender_override = "CRAB-17 Protocol") + animate(DF, pixel_z = -8, time = 5, , easing = LINEAR_EASING) + playsound(src, 'sound/weapons/mortar_whistle.ogg', 70, TRUE, 6) + addtimer(CALLBACK(src, .proc/endLaunch), 5, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation + + + +/obj/effect/dumpeetTarget/proc/endLaunch() + QDEL_NULL(DF) //Delete the falling machine effect, because at this point its animation is over. We dont use temp_visual because we want to manually delete it as soon as the pod appears + playsound(src, "explosion", 80, TRUE) + dump.forceMove(get_turf(src)) + qdel(src) //The target's purpose is complete. It can rest easy now diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index f60edf2917..a4ed8dedd1 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -91,6 +91,11 @@ refill() +/obj/item/toy/crayon/examine(mob/user) + . = ..() + if(can_change_colour) + . += "Ctrl-click [src] while it's on your person to quickly recolour it." + /obj/item/toy/crayon/proc/refill() if(charges == -1) charges_left = 100 @@ -160,6 +165,12 @@ update_icon() return TRUE +/obj/item/toy/crayon/CtrlClick(mob/user) + if(can_change_colour && !isturf(loc) && user.canUseTopic(src, BE_CLOSE, ismonkey(user))) + select_colour(user) + else + return ..() + /obj/item/toy/crayon/proc/staticDrawables() . = list() @@ -237,14 +248,7 @@ else paint_mode = PAINT_NORMAL if("select_colour") - if(can_change_colour) - var/chosen_colour = input(usr,"","Choose Color",paint_color) as color|null - - if (!isnull(chosen_colour)) - paint_color = chosen_colour - . = TRUE - else - . = FALSE + . = can_change_colour && select_colour(usr) if("enter_text") var/txt = stripped_input(usr,"Choose what to write.", "Scribbles",default = text_buffer) @@ -254,6 +258,13 @@ drawtype = "a" update_icon() +/obj/item/toy/crayon/proc/select_colour(mob/user) + var/chosen_colour = input(user, "", "Choose Color", paint_color) as color|null + if (!isnull(chosen_colour) && user.canUseTopic(src, BE_CLOSE, ismonkey(user))) + paint_color = chosen_colour + return TRUE + return FALSE + /obj/item/toy/crayon/proc/crayon_text_strip(text) var/static/regex/crayon_r = new /regex(@"[^\w!?,.=%#&+\/\-]") return replacetext(lowertext(text), crayon_r, "") diff --git a/code/game/objects/items/credit_holochip.dm b/code/game/objects/items/credit_holochip.dm new file mode 100644 index 0000000000..0acb225772 --- /dev/null +++ b/code/game/objects/items/credit_holochip.dm @@ -0,0 +1,107 @@ +/obj/item/holochip + name = "credit holochip" + desc = "A hard-light chip encoded with an amount of credits. It is a modern replacement for physical money that can be directly converted to virtual currency and viceversa. Keep away from magnets." + icon = 'icons/obj/economy.dmi' + icon_state = "holochip" + throwforce = 0 + force = 0 + w_class = WEIGHT_CLASS_TINY + var/credits = 0 + +/obj/item/holochip/Initialize(mapload, amount) + . = ..() + credits = amount + update_icon() + +/obj/item/holochip/examine(mob/user) + . = ..() + . += "It's loaded with [credits] credit[( credits > 1 ) ? "s" : ""]\n"+\ + "Alt-Click to split." + +/obj/item/holochip/get_item_credit_value() + return credits + +/obj/item/holochip/update_icon() + name = "\improper [credits] credit holochip" + var/rounded_credits = credits + switch(credits) + if(1 to 999) + icon_state = "holochip" + if(1000 to 999999) + icon_state = "holochip_kilo" + rounded_credits = round(rounded_credits * 0.001) + if(1000000 to 999999999) + icon_state = "holochip_mega" + rounded_credits = round(rounded_credits * 0.000001) + if(1000000000 to INFINITY) + icon_state = "holochip_giga" + rounded_credits = round(rounded_credits * 0.000000001) + var/overlay_color = "#914792" + switch(rounded_credits) + if(0 to 4) + overlay_color = "#8E2E38" + if(5 to 9) + overlay_color = "#914792" + if(10 to 19) + overlay_color = "#BF5E0A" + if(20 to 49) + overlay_color = "#358F34" + if(50 to 99) + overlay_color = "#676767" + if(100 to 199) + overlay_color = "#009D9B" + if(200 to 499) + overlay_color = "#0153C1" + if(500 to INFINITY) + overlay_color = "#2C2C2C" + cut_overlays() + var/mutable_appearance/holochip_overlay = mutable_appearance('icons/obj/economy.dmi', "[icon_state]-color") + holochip_overlay.color = overlay_color + add_overlay(holochip_overlay) + +/obj/item/holochip/proc/spend(amount, pay_anyway = FALSE) + if(credits >= amount) + credits -= amount + if(credits == 0) + qdel(src) + update_icon() + return amount + else if(pay_anyway) + qdel(src) + return credits + else + return 0 + +/obj/item/holochip/attackby(obj/item/I, mob/user, params) + ..() + if(istype(I, /obj/item/holochip)) + var/obj/item/holochip/H = I + credits += H.credits + to_chat(user, "You insert the credits into [src].") + update_icon() + qdel(H) + +/obj/item/holochip/AltClick(mob/user) + if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) + return + var/split_amount = round(input(user,"How many credits do you want to extract from the holochip?") as null|num) + if(split_amount == null || split_amount <= 0 || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) + return + else + var/new_credits = spend(split_amount, TRUE) + var/obj/item/holochip/H = new(user ? user : drop_location(), new_credits) + if(user) + if(!user.put_in_hands(H)) + H.forceMove(user.drop_location()) + add_fingerprint(user) + H.add_fingerprint(user) + to_chat(user, "You extract [split_amount] credits into a new holochip.") + +/obj/item/holochip/emp_act(severity) + . = ..() + if(. & EMP_PROTECT_SELF) + return + var/wipe_chance = 60 / severity + if(prob(wipe_chance)) + visible_message("[src] fizzles and disappears!") + qdel(src) //rip cash diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index 3ac3347222..7cc76da312 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -433,7 +433,7 @@ H.visible_message("The defibrillator safely discharges the excessive charge into the floor!") return var/mob/living/M = H.pulledby - if(M.electrocute_act(30, src)) + if(M.electrocute_act(30, H)) M.visible_message("[M] is electrocuted by [M.p_their()] contact with [H]!") M.emote("scream") diff --git a/code/game/objects/items/devices/dogborg_sleeper.dm b/code/game/objects/items/devices/dogborg_sleeper.dm index 2614775906..41a12136ef 100644 --- a/code/game/objects/items/devices/dogborg_sleeper.dm +++ b/code/game/objects/items/devices/dogborg_sleeper.dm @@ -3,7 +3,7 @@ /obj/item/dogborg/sleeper name = "hound sleeper" desc = "nothing should see this." - icon = 'icons/mob/dogborg.dmi' + icon = 'icons/mob/robot_items.dmi' icon_state = "sleeper" w_class = WEIGHT_CLASS_TINY var/mob/living/carbon/patient @@ -418,29 +418,15 @@ var/units = round(patient.reagents.get_reagent_amount(chem)) to_chat(hound, "Injecting [units] unit\s of [chem] into occupant.") //If they were immersed, the reagents wouldn't leave with them. -/obj/item/dogborg/sleeper/medihound //Medihound sleeper - name = "Mobile Sleeper" - desc = "Equipment for medical hound. A mounted sleeper that stabilizes patients and can inject reagents in the borg's reserves." - icon = 'icons/mob/dogborg.dmi' - icon_state = "sleeper" - breakout_time = 30 //Medical sleepers should be designed to be as easy as possible to get out of. - /obj/item/dogborg/sleeper/K9 //The K9 portabrig name = "Mobile Brig" desc = "Equipment for a K9 unit. A mounted portable-brig that holds criminals." - icon = 'icons/mob/dogborg.dmi' icon_state = "sleeperb" inject_amount = 0 min_health = -100 injection_chems = null //So they don't have all the same chems as the medihound! breakout_time = 300 -/obj/item/storage/attackby(obj/item/dogborg/sleeper/K9, mob/user, proximity) - if(istype(K9)) - K9.afterattack(src, user ,1) - else - . = ..() - /obj/item/dogborg/sleeper/K9/afterattack(mob/living/carbon/target, mob/living/silicon/user, proximity) var/mob/living/silicon/robot/hound = get_host() if(!hound || !istype(target) || !proximity || target.anchored) @@ -462,70 +448,6 @@ user.visible_message("[hound.name]'s mobile brig clunks in series as [target] slips inside.", "Your mobile brig groans lightly as [target] slips inside.") playsound(hound, 'sound/effects/bin_close.ogg', 80, 1) // Really don't need ERP sound effects for robots - -/obj/item/dogborg/sleeper/compactor //Janihound gut. - name = "garbage processor" - desc = "A mounted garbage compactor unit with fuel processor." - icon = 'icons/mob/dogborg.dmi' - icon_state = "compactor" - inject_amount = 0 - min_health = -100 - injection_chems = null //So they don't have all the same chems as the medihound! - var/max_item_count = 30 - -/obj/item/storage/attackby(obj/item/dogborg/sleeper/compactor, mob/user, proximity) //GIT CIRCUMVENTED YO! - if(istype(compactor)) - compactor.afterattack(src, user ,1) - else - . = ..() - -/obj/item/dogborg/sleeper/compactor/afterattack(atom/movable/target, mob/living/silicon/user, proximity)//GARBO NOMS - var/mob/living/silicon/robot/hound = get_host() - if(!hound || !istype(target) || !proximity || target.anchored) - return - if(length(contents) > (max_item_count - 1)) - to_chat(user,"Your [src] is full. Eject or process contents to continue.") - return - if(isitem(target)) - var/obj/item/I = target - if(CheckAccepted(I)) - to_chat(user,"[I] registers an error code to your [src]") - return - if(I.w_class > WEIGHT_CLASS_NORMAL) - to_chat(user,"[I] is too large to fit into your [src]") - return - user.visible_message("[hound.name] is ingesting [I] into their [src.name].", "You start ingesting [target] into your [src.name]...") - if(do_after(user, 15, target = target) && length(contents) < max_item_count) - I.forceMove(src) - I.visible_message("[hound.name]'s garbage processor groans lightly as [I] slips inside.", "Your garbage compactor groans lightly as [I] slips inside.") - playsound(hound, 'sound/machines/disposalflush.ogg', 50, 1) - if(length(contents) > 11) //grow that tum after a certain junk amount - hound.sleeper_r = 1 - hound.update_icons() - else - hound.sleeper_r = 0 - hound.update_icons() - return - - if(iscarbon(target) || issilicon(target)) - var/mob/living/trashman = target - if(!CHECK_BITFIELD(trashman.vore_flags,DEVOURABLE)) - to_chat(user, "[target] registers an error code to your [src]") - return - if(patient) - to_chat(user,"Your [src] is already occupied.") - return - if(trashman.buckled) - to_chat(user,"[trashman] is buckled and can not be put into your [src].") - return - user.visible_message("[hound.name] is ingesting [trashman] into their [src].", "You start ingesting [trashman] into your [src.name]...") - if(do_after(user, 30, target = trashman) && !patient && !trashman.buckled && length(contents) < max_item_count) - trashman.forceMove(src) - trashman.reset_perspective(src) - update_gut() - user.visible_message("[hound.name]'s garbage processor groans lightly as [trashman] slips inside.", "Your garbage compactor groans lightly as [trashman] slips inside.") - playsound(hound, 'sound/effects/bin_close.ogg', 80, 1) - /obj/item/dogborg/sleeper/K9/flavour name = "Recreational Sleeper" desc = "A mounted, underslung sleeper, intended for holding willing occupants for leisurely purposes." diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 7329db0679..aa8c61ae0c 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -1,6 +1,7 @@ /obj/item/flashlight name = "flashlight" desc = "A hand-held emergency light." + custom_price = 100 icon = 'icons/obj/lighting.dmi' icon_state = "flashlight" item_state = "flashlight" @@ -428,6 +429,7 @@ /obj/item/flashlight/glowstick name = "glowstick" desc = "A military-grade glowstick." + custom_price = 50 w_class = WEIGHT_CLASS_SMALL brightness_on = 4 color = LIGHT_COLOR_GREEN diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index 9c94348fc2..c931d92379 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -135,7 +135,8 @@ outmsg = "You miss the lens of [C] with [src]!" //catpeople - for(var/mob/living/carbon/human/H in view(1,targloc)) + var/list/viewers = fov_viewers(1,targloc) + for(var/mob/living/carbon/human/H in viewers) if(!iscatperson(H) || H.incapacitated() || H.eye_blind ) continue if(!H.lying) @@ -150,7 +151,7 @@ H.visible_message("[H] stares at the light"," You stare at the light... ") //cats! - for(var/mob/living/simple_animal/pet/cat/C in view(1,targloc)) + for(var/mob/living/simple_animal/pet/cat/C in viewers) if(prob(50)) C.visible_message("[C] pounces on the light!","LIGHT!") C.Move(targloc) diff --git a/code/game/objects/items/devices/polycircuit.dm b/code/game/objects/items/devices/polycircuit.dm new file mode 100644 index 0000000000..fb15ce45dc --- /dev/null +++ b/code/game/objects/items/devices/polycircuit.dm @@ -0,0 +1,52 @@ +/obj/item/stack/circuit_stack + name = "polycircuit aggregate" + desc = "A dense, overdesigned cluster of electronics which attempted to function as a multipurpose circuit electronic. Circuits can be removed from it... if you don't bleed out in the process." + icon_state = "circuit_mess" + item_state = "rods" + w_class = WEIGHT_CLASS_TINY + max_amount = 8 + var/circuit_type = /obj/item/electronics/airlock + var/chosen_circuit = "airlock" + +/obj/item/stack/circuit_stack/attack_self(mob/user)// Prevents the crafting menu, and tells you how to use it. + to_chat(user, "You can't use [src] by itself, you'll have to try and remove one of these circuits by hand... carefully.") + +/obj/item/stack/circuit_stack/attack_hand(mob/user) + var/mob/living/carbon/human/H = user + if(!user.get_inactive_held_item() == src) + return ..() + else + if(zero_amount()) + return + chosen_circuit = input("What type of circuit would you like to remove?", "Choose a Circuit Type", chosen_circuit) in list("airlock","firelock","fire alarm","air alarm","APC") + if(zero_amount()) + return + switch(chosen_circuit) + if("airlock") + circuit_type = /obj/item/electronics/airlock + if("firelock") + circuit_type = /obj/item/electronics/firelock + if("fire alarm") + circuit_type = /obj/item/electronics/firealarm + if("air alarm") + circuit_type = /obj/item/electronics/airalarm + if("APC") + circuit_type = /obj/item/electronics/apc + to_chat(user, "You spot your circuit, and carefully attempt to remove it from [src], hold still!") + if(do_after(user, 30, target = user)) + if(!src || QDELETED(src))//Sanity Check. + return + var/returned_circuit = new circuit_type(src) + user.put_in_hands(returned_circuit) + use(1) + if(!amount) + to_chat(user, "You navigate the sharp edges of circuitry and remove the last board.") + else + to_chat(user, "You navigate the sharp edges of circuitry and remove a single board from [src]") + else + H.apply_damage(15, BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + to_chat(user, "You give yourself a wicked cut on [src]'s many sharp corners and edges!") + ..() + +/obj/item/stack/circuit_stack/full + amount = 8 diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index ada598866b..f4c317c8ba 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -2,6 +2,7 @@ name = "station intercom" desc = "Talk through this." icon_state = "intercom" + plane = ABOVE_WALL_PLANE anchored = TRUE w_class = WEIGHT_CLASS_BULKY canhear_range = 2 diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 60b93d9461..5fe9de75aa 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -98,7 +98,7 @@ /obj/item/radio/ComponentInitialize() . = ..() - AddComponent(/datum/component/empprotection, EMP_PROTECT_WIRES) + AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES) /obj/item/radio/interact(mob/user) if(unscrewed && !isAI(user)) @@ -199,7 +199,7 @@ if(!spans) spans = list(M.speech_span) if(!language) - language = M.get_default_language() + language = M.get_selected_language() INVOKE_ASYNC(src, .proc/talk_into_impl, M, message, channel, spans.Copy(), language) return ITALICS | REDUCE_RANGE diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index b6cab8b438..a7b22a4c30 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -11,6 +11,7 @@ SLIME SCANNER /obj/item/t_scanner name = "\improper T-ray scanner" desc = "A terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes." + custom_price = 150 icon = 'icons/obj/device.dmi' icon_state = "t-ray0" var/on = FALSE diff --git a/code/game/objects/items/devices/sensor_device.dm b/code/game/objects/items/devices/sensor_device.dm index 79d26776a9..a92d9221c2 100644 --- a/code/game/objects/items/devices/sensor_device.dm +++ b/code/game/objects/items/devices/sensor_device.dm @@ -5,6 +5,7 @@ icon_state = "scanner" w_class = WEIGHT_CLASS_SMALL slot_flags = ITEM_SLOT_BELT + custom_price = 900 /obj/item/sensor_device/attack_self(mob/user) GLOB.crewmonitor.show(user,src) //Proc already exists, just had to call it diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm index e2140bd0fd..c785c22813 100644 --- a/code/game/objects/items/flamethrower.dm +++ b/code/game/objects/items/flamethrower.dm @@ -196,9 +196,8 @@ sleep(1) previousturf = T operating = FALSE - for(var/mob/M in viewers(1, loc)) - if((M.client && M.machine == src)) - attack_self(M) + if(usr.machine == src) + attack_self(usr) /obj/item/flamethrower/proc/default_ignite(turf/target, release_amount = 0.05) diff --git a/code/game/objects/items/granters.dm b/code/game/objects/items/granters.dm index 0a705df91c..bafffa18e3 100644 --- a/code/game/objects/items/granters.dm +++ b/code/game/objects/items/granters.dm @@ -249,10 +249,8 @@ /obj/item/book/granter/spell/smoke/recoil(mob/user) ..() to_chat(user,"Your stomach rumbles...") - if(user.nutrition) - user.nutrition = 200 - if(user.nutrition <= 0) - user.nutrition = 0 + if(user.nutrition > NUTRITION_LEVEL_STARVING + 50) + user.set_nutrition(NUTRITION_LEVEL_STARVING + 50) /obj/item/book/granter/spell/blind spell = /obj/effect/proc_holder/spell/targeted/trigger/blind diff --git a/code/game/objects/items/grenades/antigravity.dm b/code/game/objects/items/grenades/antigravity.dm index 43b2f94986..a4bc207be0 100644 --- a/code/game/objects/items/grenades/antigravity.dm +++ b/code/game/objects/items/grenades/antigravity.dm @@ -2,16 +2,16 @@ name = "antigravity grenade" icon_state = "emp" item_state = "emp" - + var/range = 7 var/forced_value = 0 var/duration = 300 /obj/item/grenade/antigravity/prime() update_mob() - + for(var/turf/T in view(range,src)) - var/datum/component/C = T.AddComponent(/datum/component/forced_gravity,forced_value) - QDEL_IN(C,duration) - + T.AddElement(/datum/element/forced_gravity, forced_value) + addtimer(CALLBACK(T, /datum/.proc/_RemoveElement, list(forced_value)), duration) + qdel(src) diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm index acd71c57ac..91dde2899d 100644 --- a/code/game/objects/items/grenades/chem_grenade.dm +++ b/code/game/objects/items/grenades/chem_grenade.dm @@ -97,8 +97,7 @@ to_chat(user, "You add [A] to the [initial(name)] assembly.") else if(stage == EMPTY && istype(I, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C = I - if (C.use(1)) + if (I.use_tool(src, user, 0, 1, max_level = JOB_SKILL_BASIC)) det_time = 50 // In case the cable_coil was removed and readded. stage_change(WIRED) to_chat(user, "You rig the [initial(name)] assembly.") diff --git a/code/game/objects/items/grenades/plastic.dm b/code/game/objects/items/grenades/plastic.dm index 66869d6f04..fe2a27f1a8 100644 --- a/code/game/objects/items/grenades/plastic.dm +++ b/code/game/objects/items/grenades/plastic.dm @@ -26,7 +26,7 @@ /obj/item/grenade/plastic/ComponentInitialize() . = ..() - AddComponent(/datum/component/empprotection, EMP_PROTECT_WIRES) + AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES) /obj/item/grenade/plastic/Destroy() qdel(nadeassembly) diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index 1e0a6ce6dc..c7c9fa37a9 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -118,7 +118,7 @@ righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' custom_materials = list(/datum/material/iron=150, /datum/material/glass=75) breakouttime = 300 //Deciseconds = 30s - cuffsound = 'sound/weapons/cablecuff.ogg' + cuffsound = 'sound/weapons/cablecuff.ogg' /obj/item/restraints/handcuffs/cable/attack_self(mob/user) to_chat(user, "You start unwinding the cable restraints back into coil") @@ -130,7 +130,7 @@ user.put_in_hands(coil) coil.color = color to_chat(user, "You unwind the cable restraints back into coil") - + /obj/item/restraints/handcuffs/cable/red color = "#ff0000" @@ -225,7 +225,6 @@ /obj/item/restraints/handcuffs/fake/kinky name = "kinky handcuffs" desc = "Fake handcuffs meant for erotic roleplay." - icon = 'modular_citadel/icons/obj/items_and_weapons.dmi' icon_state = "handcuffgag" item_state = "kinkycuff" @@ -252,7 +251,7 @@ throw_range = 1 icon_state = "beartrap" desc = "A trap used to catch bears and other legged creatures." - var/armed = 0 + var/armed = FALSE var/trap_damage = 20 /obj/item/restraints/legcuffs/beartrap/Initialize() @@ -275,14 +274,14 @@ if(armed && isturf(src.loc)) if(isliving(AM)) var/mob/living/L = AM - var/snap = 0 + var/snap = FALSE var/def_zone = BODY_ZONE_CHEST if(iscarbon(L)) var/mob/living/carbon/C = L - snap = 1 if(!C.lying) def_zone = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) if(!C.legcuffed && C.get_num_legs(FALSE) >= 2) //beartrap can't cuff your leg if there's already a beartrap or legcuffs, or you don't have two legs. + snap = TRUE C.legcuffed = src forceMove(C) C.update_equipment_speed_mods() @@ -291,21 +290,21 @@ else if(isanimal(L)) var/mob/living/simple_animal/SA = L if(SA.mob_size > MOB_SIZE_TINY) - snap = 1 - if(L.movement_type & FLYING) - snap = 0 + snap = TRUE + if(L.movement_type & (FLYING | FLOATING)) + snap = FALSE if(snap) - armed = 0 + armed = FALSE icon_state = "[initial(icon_state)][armed]" playsound(src.loc, 'sound/effects/snap.ogg', 50, 1) L.visible_message("[L] triggers \the [src].", \ "You trigger \the [src]!") - L.apply_damage(trap_damage,BRUTE, def_zone) + L.apply_damage(trap_damage, BRUTE, def_zone) ..() /obj/item/restraints/legcuffs/beartrap/energy name = "energy snare" - armed = 1 + armed = TRUE icon_state = "e_snare" trap_damage = 0 item_flags = DROPDEL diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm index 171b5a465a..381257721e 100644 --- a/code/game/objects/items/holy_weapons.dm +++ b/code/game/objects/items/holy_weapons.dm @@ -519,7 +519,9 @@ S.name = name S.ckey = C.ckey S.status_flags |= GODMODE - S.language_holder = user.language_holder.copy(S) + S.copy_languages(user, LANGUAGE_MASTER) //Make sure the sword can understand and communicate with the user. + S.update_atom_languages() + grant_all_languages(FALSE, FALSE, TRUE) //Grants omnitongue S.AddElement(/datum/element/ghost_role_eligibility,penalize_on_ghost = TRUE) START_PROCESSING(SSprocessing,src) var/input = stripped_input(S,"What are you named?", ,"", MAX_NAME_LEN) diff --git a/code/game/objects/items/implants/implantpad.dm b/code/game/objects/items/implants/implantpad.dm index 7c863017a1..4766e534c9 100644 --- a/code/game/objects/items/implants/implantpad.dm +++ b/code/game/objects/items/implants/implantpad.dm @@ -66,7 +66,7 @@ if(ismob(loc)) attack_self(loc) else - for(var/mob/M in viewers(1, src)) + for(var/mob/M in fov_viewers(1, src)) if(M.client) attack_self(M) add_fingerprint(usr) diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm index f6e52181ef..168bca0b9a 100644 --- a/code/game/objects/items/kitchen.dm +++ b/code/game/objects/items/kitchen.dm @@ -71,6 +71,7 @@ sharpness = IS_SHARP_ACCURATE armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) var/bayonet = FALSE //Can this be attached to a gun? + custom_price = 250 /obj/item/kitchen/knife/Initialize() . = ..() @@ -130,6 +131,7 @@ custom_materials = list(/datum/material/iron=18000) attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") w_class = WEIGHT_CLASS_NORMAL + custom_price = 600 /obj/item/kitchen/knife/combat name = "combat knife" @@ -197,6 +199,7 @@ throw_range = 7 w_class = WEIGHT_CLASS_NORMAL attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") + custom_price = 200 /obj/item/kitchen/rollingpin/suicide_act(mob/living/carbon/user) user.visible_message("[user] begins flattening [user.p_their()] head with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!") diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 2923e35bf7..a3ea433fda 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -304,7 +304,7 @@ return else if(cooldown_check < world.time) - if(target.run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user) & BLOCK_SUCCESS) + if(target.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, null) & BLOCK_SUCCESS) playsound(target, 'sound/weapons/genhit.ogg', 50, 1) return if(ishuman(target)) @@ -325,7 +325,7 @@ else target.LAssailant = WEAKREF(user) cooldown_check = world.time + cooldown - user.adjustStaminaLossBuffered(getweight())//CIT CHANGE - makes swinging batons cost stamina + user.adjustStaminaLossBuffered(getweight(user, STAM_COST_BATON_MOB_MULT)) else var/wait_desc = get_wait_description() if(wait_desc) diff --git a/code/game/objects/items/pinpointer.dm b/code/game/objects/items/pinpointer.dm index 090c2f6d57..a1652fd211 100644 --- a/code/game/objects/items/pinpointer.dm +++ b/code/game/objects/items/pinpointer.dm @@ -78,6 +78,7 @@ name = "crew pinpointer" desc = "A handheld tracking device that points to crew suit sensors." icon_state = "pinpointer_crew" + custom_price = 600 var/has_owner = FALSE var/pinpointer_owner = null diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index abb2d12a1f..2f697553f5 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -11,7 +11,7 @@ var/charge_cost = 30 /obj/item/borg/stun/attack(mob/living/M, mob/living/user) - if(M.run_block(src, 0, "[M]'s [name]", ATTACK_TYPE_MELEE, 0, user, ran_zone(user.zone_selected)) & BLOCK_SUCCESS) + if(M.mob_run_block(src, 0, "[M]'s [name]", ATTACK_TYPE_MELEE, 0, user, ran_zone(user.zone_selected), null) & BLOCK_SUCCESS) playsound(M, 'sound/weapons/genhit.ogg', 50, 1) return FALSE if(iscyborg(user)) @@ -419,7 +419,7 @@ A.BB.damage = hitdamage if(hitdamage) A.BB.nodamage = FALSE - A.BB.speed = 0.5 + A.BB.pixels_per_second = TILES_TO_PIXELS(20) playsound(src.loc, 'sound/machines/click.ogg', 50, 1) A.fire_casing(target, user, params, 0, 0, null, 0, src) user.visible_message("[user] blasts a flying lollipop at [target]!") @@ -434,7 +434,7 @@ A.BB.damage = hitdamage if(hitdamage) A.BB.nodamage = FALSE - A.BB.speed = 0.5 + A.BB.pixels_per_second = TILES_TO_PIXELS(20) A.BB.color = rgb(rand(0, 255), rand(0, 255), rand(0, 255)) playsound(src.loc, 'sound/weapons/bulletflyby3.ogg', 50, 1) A.fire_casing(target, user, params, 0, 0, null, 0, src) @@ -671,13 +671,13 @@ if(track_projectile) tracked[P] = P.damage P.damage *= projectile_damage_coefficient - P.speed *= projectile_speed_coefficient + P.pixels_per_second *= projectile_speed_coefficient P.add_overlay(projectile_effect) /obj/item/borg/projectile_dampen/proc/restore_projectile(obj/item/projectile/P) tracked -= P P.damage *= (1/projectile_damage_coefficient) - P.speed *= (1/projectile_speed_coefficient) + P.pixels_per_second *= (1/projectile_speed_coefficient) P.cut_overlay(projectile_effect) /********************************************************************** @@ -902,4 +902,47 @@ name = "mining point card" desc = "A robotic ID strip used for claiming and transferring mining points. Must be held in an active slot to transfer points." access = list(ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MAILSORTING, ACCESS_MINERAL_STOREROOM) - icon_state = "data_1" \ No newline at end of file + icon_state = "data_1" + + +///Mere cosmetic dogborg items, remnants of what were once the most annoying cyborg modules. +/obj/item/dogborg_tongue + name = "synthetic tongue" + desc = "Useful for slurping mess off the floor before affectionally licking the crew members in the face." + icon = 'icons/mob/robot_items.dmi' + icon_state = "synthtongue" + hitsound = 'sound/effects/attackblob.ogg' + desc = "For giving affectionate kisses." + item_flags = NOBLUDGEON + +/obj/item/dogborg_tongue/afterattack(atom/target, mob/user, proximity) + . = ..() + if(!proximity || !isliving(target)) + return + var/mob/living/silicon/robot/R = user + var/mob/living/L = target + if(L.ckey && !(L.client?.prefs.vore_flags & LICKABLE)) + to_chat(R, "ERROR ERROR: Target not lickable. Aborting display-of-affection subroutine.") + return + + if(check_zone(R.zone_selected) == "head") + R.visible_message("\the [R] affectionally licks \the [L]'s face!", "You affectionally lick \the [L]'s face!") + playsound(R, 'sound/effects/attackblob.ogg', 50, 1) + else + R.visible_message("\the [R] affectionally licks \the [L]!", "You affectionally lick \the [L]!") + playsound(R, 'sound/effects/attackblob.ogg', 50, 1) + +/obj/item/dogborg_nose + name = "boop module" + desc = "The BOOP module" + icon = 'icons/mob/robot_items.dmi' + icon_state = "nose" + flags_1 = CONDUCT_1|NOBLUDGEON + force = 0 + +/obj/item/dogborg_nose/afterattack(atom/target, mob/user, proximity) + . = ..() + if(!proximity) + return + do_attack_animation(target, null, src) + user.visible_message("[user] [pick("nuzzles", "pushes", "boops")] \the [target.name] with their nose!") diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm index 30e1460f8a..65c027217c 100644 --- a/code/game/objects/items/shields.dm +++ b/code/game/objects/items/shields.dm @@ -203,10 +203,10 @@ if(obj_integrity >= max_integrity) to_chat(user, "[src] is already in perfect condition.") else - var/obj/item/stack/sheet/mineral/titanium/T = W - T.use(1) + var/obj/item/stack/S = W + S.use(1) obj_integrity = max_integrity - to_chat(user, "You repair [src] with [T].") + to_chat(user, "You repair [src] with [S].") else return ..() diff --git a/code/game/objects/items/stacks/cash.dm b/code/game/objects/items/stacks/cash.dm index 94f6fca28c..ce0bc6591a 100644 --- a/code/game/objects/items/stacks/cash.dm +++ b/code/game/objects/items/stacks/cash.dm @@ -4,7 +4,7 @@ icon = 'icons/obj/economy.dmi' icon_state = "spacecash" amount = 1 - max_amount = 20 + max_amount = INFINITY throwforce = 0 throw_speed = 2 throw_range = 2 @@ -18,9 +18,11 @@ update_desc() /obj/item/stack/spacecash/proc/update_desc() - var/total_worth = amount*value + var/total_worth = get_item_credit_value() desc = "It's worth [total_worth] credit[( total_worth > 1 ) ? "s" : ""]" +/obj/item/stack/spacecash/get_item_credit_value() + return (amount*value) /obj/item/stack/spacecash/merge(obj/item/stack/S) . = ..() @@ -69,3 +71,9 @@ icon_state = "spacecash1000" singular_name = "one thousand credit bill" value = 1000 + +/obj/item/stack/spacecash/c10000 + icon_state = "spacecash10000" + singular_name = "ten thousand credit bill" + value = 10000 + diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index adc4970175..59a993ad96 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -59,6 +59,9 @@ self_delay = 20 grind_results = list(/datum/reagent/medicine/styptic_powder = 10) +/obj/item/stack/medical/bruise_pack/one + amount = 1 + /obj/item/stack/medical/bruise_pack/heal(mob/living/M, mob/user) if(M.stat == DEAD) to_chat(user, " [M] is dead. You can not help [M.p_them()]!") @@ -93,6 +96,7 @@ var/stop_bleeding = 1800 var/heal_brute = 5 self_delay = 10 + custom_price = 100 /obj/item/stack/medical/gauze/heal(mob/living/M, mob/user) if(ishuman(M)) @@ -134,6 +138,9 @@ singular_name = "sterilized medical gauze" self_delay = 5 +/obj/item/stack/medical/gauze/adv/one + amount = 1 + /obj/item/stack/medical/gauze/cyborg custom_materials = null is_cyborg = 1 @@ -151,6 +158,9 @@ self_delay = 20 grind_results = list(/datum/reagent/medicine/silver_sulfadiazine = 10) +/obj/item/stack/medical/ointment/one + amount = 1 + /obj/item/stack/medical/ointment/heal(mob/living/M, mob/user) if(M.stat == DEAD) to_chat(user, " [M] is dead. You can not help [M.p_them()]!") diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index e919f3fe02..4c2c21a7db 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -89,3 +89,19 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \ /obj/item/stack/rods/fifty amount = 50 + +/obj/item/stack/rods/lava + name = "heat resistant rod" + desc = "Treated, specialized metal rods. When exposed to the vaccum of space their coating breaks off, but they can hold up against the extreme heat of active lava." + singular_name = "heat resistant rod" + icon_state = "rods" + item_state = "rods" + color = "#5286b9ff" + flags_1 = CONDUCT_1 + w_class = WEIGHT_CLASS_NORMAL + custom_materials = list(/datum/material/iron=1000, /datum/material/plasma=500, /datum/material/titanium=2000) + max_amount = 30 + resistance_flags = FIRE_PROOF | LAVA_PROOF + +/obj/item/stack/rods/lava/thirty + amount = 30 diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index fa218c5caa..c34ad44d5c 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -69,7 +69,7 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \ if (get_amount() < 1 || CC.get_amount() < 5) to_chat(user, "You attach wire to the [name].") var/obj/item/stack/light_w/new_tile = new(user.loc) diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index f19dbb2a6b..5f2b9fda41 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -5,7 +5,6 @@ * Wood * Bamboo * Cloth - * Silk * Durathread * Cardboard * Runed Metal (cult) @@ -63,7 +62,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \ new/datum/stack_recipe("floor tile", /obj/item/stack/tile/plasteel, 1, 4, 20), \ new/datum/stack_recipe("metal rod", /obj/item/stack/rods, 1, 2, 60), \ null, \ - new/datum/stack_recipe("wall girders", /obj/structure/girder, 2, time = 40, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("wall girders", /obj/structure/girder, 2, time = 40, one_per_turf = TRUE, on_floor = TRUE, trait_booster = TRAIT_QUICK_BUILD, trait_modifier = 0.75), \ null, \ new/datum/stack_recipe("computer frame", /obj/structure/frame/computer, 5, time = 25, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("modular console", /obj/machinery/modular_computer/console/buildable/, 10, time = 25, one_per_turf = TRUE, on_floor = TRUE), \ @@ -268,6 +267,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ new/datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 50),\ null, \ new/datum/stack_recipe("picture frame", /obj/item/wallframe/picture, 1, time = 10),\ + new/datum/stack_recipe("painting frame", /obj/item/wallframe/painting, 1, time = 10),\ new/datum/stack_recipe("mortar", /obj/item/reagent_containers/glass/mortar, 3), \ new/datum/stack_recipe("honey frame", /obj/item/honey_frame, 5, time = 10),\ )) @@ -388,6 +388,9 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \ null, \ new/datum/stack_recipe("blindfold", /obj/item/clothing/glasses/sunglasses/blindfold, 2), \ null, \ + new/datum/stack_recipe("19x19 canvas", /obj/item/canvas/nineteenXnineteen, 3), \ + new/datum/stack_recipe("23x19 canvas", /obj/item/canvas/twentythreeXnineteen, 4), \ + new/datum/stack_recipe("23x23 canvas", /obj/item/canvas/twentythreeXtwentythree, 5), \ )) /obj/item/stack/sheet/cloth @@ -401,7 +404,6 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \ throwforce = 0 pull_effort = 90 is_fabric = TRUE - loom_result = /obj/item/stack/sheet/silk merge_type = /obj/item/stack/sheet/cloth /obj/item/stack/sheet/cloth/get_main_recipes() @@ -414,30 +416,6 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \ /obj/item/stack/sheet/cloth/thirty amount = 30 -/* - * Silk - */ - - GLOBAL_LIST_INIT(silk_recipes, list ( \ - new/datum/stack_recipe("white jumpsuit", /obj/item/clothing/under/color/white, 4, time = 40), \ - new/datum/stack_recipe("white gloves", /obj/item/clothing/gloves/color/white, 2, time = 40), \ - null, \ - new/datum/stack_recipe("silk string", /obj/item/weaponcrafting/silkstring, 1, time = 40), \ - )) - -/obj/item/stack/sheet/silk - name = "silk" - desc = "A long, soft material. Made out of refined cotton, instead of relying on the habits of spiders or silkworms." - singular_name = "silk sheet" - icon_state = "sheet-silk" - item_state = "sheet-cloth" - novariants = TRUE - merge_type = /obj/item/stack/sheet/silk - -/obj/item/stack/sheet/silk/get_main_recipes() - . = ..() - . += GLOB.silk_recipes - /* * Durathread */ @@ -446,6 +424,7 @@ GLOBAL_LIST_INIT(durathread_recipes, list ( \ new/datum/stack_recipe("durathread beret", /obj/item/clothing/head/beret/durathread, 2, time = 40), \ new/datum/stack_recipe("durathread beanie", /obj/item/clothing/head/beanie/durathread, 2, time = 40), \ new/datum/stack_recipe("durathread bandana", /obj/item/clothing/mask/bandana/durathread, 1, time = 25), \ + new/datum/stack_recipe("durathread string", /obj/item/weaponcrafting/durathread_string, 1, time = 40) \ )) /obj/item/stack/sheet/durathread diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index add9ebd6b2..2c8e700316 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -201,8 +201,13 @@ if(!building_checks(R, multiplier)) return if (R.time) + var/adjusted_time = 0 usr.visible_message("[usr] starts building [R.title].", "You start building [R.title]...") - if (!do_after(usr, R.time, target = usr)) + if(HAS_TRAIT(usr, R.trait_booster)) + adjusted_time = (R.time * R.trait_modifier) + else + adjusted_time = R.time + if (!do_after(usr, adjusted_time, target = usr)) return if(!building_checks(R, multiplier)) return @@ -457,8 +462,10 @@ var/window_checks = FALSE var/placement_checks = FALSE var/applies_mats = FALSE + var/trait_booster = null + var/trait_modifier = 1 -/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1,time = 0, one_per_turf = FALSE, on_floor = FALSE, window_checks = FALSE, placement_checks = FALSE, applies_mats = FALSE) +/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1,time = 0, one_per_turf = FALSE, on_floor = FALSE, window_checks = FALSE, placement_checks = FALSE, applies_mats = FALSE, trait_booster = null, trait_modifier = 1) src.title = title @@ -472,6 +479,8 @@ src.window_checks = window_checks src.placement_checks = placement_checks src.applies_mats = applies_mats + src.trait_booster = trait_booster + src.trait_modifier = trait_modifier /* * Recipe list datum */ diff --git a/code/game/objects/items/storage/storage.dm b/code/game/objects/items/storage/_storage.dm similarity index 100% rename from code/game/objects/items/storage/storage.dm rename to code/game/objects/items/storage/_storage.dm diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index a4d9636414..3d5f0dc924 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -24,9 +24,9 @@ /obj/item/storage/backpack/ComponentInitialize() . = ..() var/datum/component/storage/STR = GetComponent(/datum/component/storage) - STR.max_combined_w_class = 21 - STR.max_w_class = WEIGHT_CLASS_NORMAL - STR.max_items = 21 + STR.storage_flags = STORAGE_FLAGS_VOLUME_DEFAULT + STR.max_volume = STORAGE_VOLUME_BACKPACK + STR.max_w_class = MAX_WEIGHT_CLASS_BACKPACK /* * Backpack Types @@ -64,9 +64,9 @@ /obj/item/storage/backpack/holding/ComponentInitialize() . = ..() var/datum/component/storage/STR = GetComponent(/datum/component/storage) - STR.allow_big_nesting = TRUE - STR.max_w_class = WEIGHT_CLASS_BULKY - STR.max_combined_w_class = 35 + STR.max_w_class = MAX_WEIGHT_CLASS_BAG_OF_HOLDING + STR.storage_flags = STORAGE_FLAGS_VOLUME_DEFAULT + STR.max_volume = STORAGE_VOLUME_BAG_OF_HOLDING /obj/item/storage/backpack/holding/suicide_act(mob/living/user) user.visible_message("[user] is jumping into [src]! It looks like [user.p_theyre()] trying to commit suicide.") @@ -344,7 +344,7 @@ /obj/item/storage/backpack/duffelbag/ComponentInitialize() . = ..() var/datum/component/storage/STR = GetComponent(/datum/component/storage) - STR.max_combined_w_class = 30 + STR.max_volume = STORAGE_VOLUME_DUFFLEBAG /obj/item/storage/backpack/duffelbag/captain name = "captain's duffel bag" diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm index 52802fa3df..5b7eb65d9b 100644 --- a/code/game/objects/items/storage/bags.dm +++ b/code/game/objects/items/storage/bags.dm @@ -61,7 +61,7 @@ switch(contents.len) if(0) icon_state = "[initial(icon_state)]" - if(0 to 11) + if(1 to 11) icon_state = "[initial(icon_state)]1" if(11 to 20) icon_state = "[initial(icon_state)]2" diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index 97b7ee8a38..82ae274012 100755 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -43,6 +43,7 @@ icon_state = "utilitybelt" item_state = "utility" content_overlays = TRUE + custom_premium_price = 300 rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE //because this is easier than trying to have showers wash all contents. /obj/item/storage/belt/utility/ComponentInitialize() @@ -712,6 +713,7 @@ icon_state = "fannypack_leather" item_state = "fannypack_leather" dying_key = DYE_REGISTRY_FANNYPACK + custom_price = 100 /obj/item/storage/belt/fannypack/ComponentInitialize() . = ..() diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm index ec443d4e48..c5b48164a0 100644 --- a/code/game/objects/items/storage/boxes.dm +++ b/code/game/objects/items/storage/boxes.dm @@ -622,6 +622,7 @@ item_state = "zippo" w_class = WEIGHT_CLASS_TINY slot_flags = ITEM_SLOT_BELT + custom_price = 20 /obj/item/storage/box/matches/ComponentInitialize() . = ..() @@ -850,12 +851,6 @@ -#define NODESIGN "None" -#define NANOTRASEN "NanotrasenStandard" -#define SYNDI "SyndiSnacks" -#define HEART "Heart" -#define SMILEY "SmileyFace" - /obj/item/storage/box/papersack name = "paper sack" desc = "A sack neatly crafted out of paper." @@ -863,7 +858,18 @@ item_state = "paperbag_None" resistance_flags = FLAMMABLE foldable = null - var/design = NODESIGN + /// A list of all available papersack reskins + var/list/papersack_designs = list() + +/obj/item/storage/box/papersack/Initialize(mapload) + . = ..() + papersack_designs = sortList(list( + "None" = image(icon = src.icon, icon_state = "paperbag_None"), + "NanotrasenStandard" = image(icon = src.icon, icon_state = "paperbag_NanotrasenStandard"), + "SyndiSnacks" = image(icon = src.icon, icon_state = "paperbag_SyndiSnacks"), + "Heart" = image(icon = src.icon, icon_state = "paperbag_Heart"), + "SmileyFace" = image(icon = src.icon, icon_state = "paperbag_SmileyFace") + )) /obj/item/storage/box/papersack/update_icon_state() if(contents.len == 0) @@ -871,55 +877,64 @@ else icon_state = "[item_state]_closed" + /obj/item/storage/box/papersack/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/pen)) - //if a pen is used on the sack, dialogue to change its design appears - if(contents.len) - to_chat(user, "You can't modify [src] with items still inside!") - return - var/list/designs = list(NODESIGN, NANOTRASEN, SYNDI, HEART, SMILEY, "Cancel") - var/switchDesign = input("Select a Design:", "Paper Sack Design", designs[1]) in designs - if(get_dist(usr, src) > 1) - to_chat(usr, "You have moved too far away!") - return - var/choice = designs.Find(switchDesign) - if(design == designs[choice] || designs[choice] == "Cancel") - return 0 - to_chat(usr, "You make some modifications to [src] using your pen.") - design = designs[choice] - icon_state = "paperbag_[design]" - item_state = "paperbag_[design]" - switch(designs[choice]) - if(NODESIGN) + var/choice = show_radial_menu(user, src , papersack_designs, custom_check = CALLBACK(src, .proc/check_menu, user, W), radius = 36, require_near = TRUE) + if(!choice) + return FALSE + if(icon_state == "paperbag_[choice]") + return FALSE + switch(choice) + if("None") desc = "A sack neatly crafted out of paper." - if(NANOTRASEN) + if("NanotrasenStandard") desc = "A standard Nanotrasen paper lunch sack for loyal employees on the go." - if(SYNDI) + if("SyndiSnacks") desc = "The design on this paper sack is a remnant of the notorious 'SyndieSnacks' program." - if(HEART) + if("Heart") desc = "A paper sack with a heart etched onto the side." - if(SMILEY) + if("SmileyFace") desc = "A paper sack with a crude smile etched onto the side." - return 0 + else + return FALSE + to_chat(user, "You make some modifications to [src] using your pen.") + icon_state = "paperbag_[choice]" + item_state = "paperbag_[choice]" + return FALSE else if(W.get_sharpness()) if(!contents.len) if(item_state == "paperbag_None") user.show_message("You cut eyeholes into [src].", MSG_VISUAL) new /obj/item/clothing/head/papersack(user.loc) qdel(src) - return 0 + return FALSE else if(item_state == "paperbag_SmileyFace") user.show_message("You cut eyeholes into [src] and modify the design.", MSG_VISUAL) new /obj/item/clothing/head/papersack/smiley(user.loc) qdel(src) - return 0 + return FALSE return ..() -#undef NODESIGN -#undef NANOTRASEN -#undef SYNDI -#undef HEART -#undef SMILEY +/** + * check_menu: Checks if we are allowed to interact with a radial menu + * + * Arguments: + * * user The mob interacting with a menu + * * P The pen used to interact with a menu + */ +/obj/item/storage/box/papersack/proc/check_menu(mob/user, obj/item/pen/P) + if(!istype(user)) + return FALSE + if(user.incapacitated()) + return FALSE + if(contents.len) + to_chat(user, "You can't modify [src] with items still inside!") + return FALSE + if(!P || !user.is_holding(P)) + to_chat(user, "You need a pen to modify [src]!") + return FALSE + return TRUE /obj/item/storage/box/ingredients //This box is for the randomly chosen version the chef spawns with, it shouldn't actually exist. name = "ingredients box" diff --git a/code/game/objects/items/storage/fancy.dm b/code/game/objects/items/storage/fancy.dm index f32532537b..685a3b59f6 100644 --- a/code/game/objects/items/storage/fancy.dm +++ b/code/game/objects/items/storage/fancy.dm @@ -136,6 +136,7 @@ slot_flags = ITEM_SLOT_BELT icon_type = "cigarette" spawn_type = /obj/item/clothing/mask/cigarette/space_cigarette + custom_price = 75 /obj/item/storage/fancy/cigarettes/ComponentInitialize() . = ..() @@ -277,6 +278,7 @@ ///The value in here has NOTHING to do with icons. It needs to be this for the proper examine. icon_type = "rolling paper" spawn_type = /obj/item/rollingpaper + custom_price = 25 /obj/item/storage/fancy/rollingpapers/ComponentInitialize() . = ..() diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm index 01193d0e21..092648ee3c 100644 --- a/code/game/objects/items/storage/firstaid.dm +++ b/code/game/objects/items/storage/firstaid.dm @@ -223,6 +223,8 @@ /obj/item/storage/pill_bottle/ComponentInitialize() . = ..() var/datum/component/storage/STR = GetComponent(/datum/component/storage) + STR.storage_flags = STORAGE_FLAGS_VOLUME_DEFAULT + STR.max_volume = 14 STR.allow_quick_gather = TRUE STR.click_gather = TRUE STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/dice)) @@ -244,7 +246,7 @@ desc = "Contains pills used to counter radiation poisoning." /obj/item/storage/pill_bottle/anitrad/PopulateContents() - for(var/i in 1 to 5) + for(var/i in 1 to 4) new /obj/item/reagent_containers/pill/antirad(src) /obj/item/storage/pill_bottle/epinephrine @@ -276,7 +278,7 @@ desc = "Guaranteed to give you that extra burst of energy during a long shift!" /obj/item/storage/pill_bottle/stimulant/PopulateContents() - for(var/i in 1 to 5) + for(var/i in 1 to 4) new /obj/item/reagent_containers/pill/stimulant(src) /obj/item/storage/pill_bottle/mining @@ -373,7 +375,7 @@ ///////////// /obj/item/storage/belt/organbox - name = "Organ Storge" + name = "Organ Storage" desc = "A compact box that helps hold massive amounts of implants, organs, and some tools. Has a belt clip for easy carrying" w_class = WEIGHT_CLASS_BULKY icon = 'icons/obj/mysterybox.dmi' @@ -392,6 +394,12 @@ STR.can_hold = typecacheof(list( /obj/item/storage/pill_bottle, /obj/item/reagent_containers/hypospray, + /obj/item/pinpointer/crew, + /obj/item/tele_iv, + /obj/item/sequence_scanner, + /obj/item/sensor_device, + /obj/item/bodybag, + /obj/item/surgicaldrill/advanced, /obj/item/healthanalyzer, /obj/item/reagent_containers/syringe, /obj/item/clothing/glasses/hud/health, @@ -407,6 +415,8 @@ /obj/item/implantcase, /obj/item/implanter, /obj/item/circuitboard/computer/operating, + /obj/item/circuitboard/computer/crew, + /obj/item/stack/sheet/glass, /obj/item/stack/sheet/mineral/silver, /obj/item/organ_storage )) @@ -422,6 +432,8 @@ throw_range = 7 var/empty = FALSE item_state = "firstaid" + custom_price = 300 + custom_premium_price = 500 /obj/item/storage/hypospraykit/ComponentInitialize() . = ..() diff --git a/code/game/objects/items/storage/secure.dm b/code/game/objects/items/storage/secure.dm index e177a9f9fd..ef70bd201d 100644 --- a/code/game/objects/items/storage/secure.dm +++ b/code/game/objects/items/storage/secure.dm @@ -105,10 +105,7 @@ if (length(code) > 5) code = "ERROR" add_fingerprint(usr) - for(var/mob/M in viewers(1, loc)) - if ((M.client && M.machine == src)) - attack_self(M) - return + attack_self(usr) return @@ -158,6 +155,7 @@ /obj/item/storage/secure/safe name = "secure safe" icon = 'icons/obj/storage.dmi' + plane = ABOVE_WALL_PLANE icon_state = "safe" icon_opened = "safe0" icon_locking = "safeb" diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm index 64e0a6b492..7e89ddbd8d 100644 --- a/code/game/objects/items/storage/toolbox.dm +++ b/code/game/objects/items/storage/toolbox.dm @@ -16,12 +16,17 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) attack_verb = list("robusted") hitsound = 'sound/weapons/smash.ogg' custom_materials = list(/datum/material/iron = 500) - material_flags = MATERIAL_COLOR var/latches = "single_latch" var/has_latches = TRUE var/can_rubberify = TRUE rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE //very protecc too +/obj/item/storage/toolbox/greyscale + icon_state = "toolbox_default" + item_state = "toolbox_default" + can_rubberify = FALSE + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS | MATERIAL_EFFECTS + /obj/item/storage/toolbox/Initialize(mapload) if(has_latches) if(prob(10)) @@ -48,7 +53,6 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) name = "emergency toolbox" icon_state = "red" item_state = "toolbox_red" - material_flags = NONE /obj/item/storage/toolbox/emergency/PopulateContents() new /obj/item/crowbar/red(src) @@ -73,7 +77,6 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) name = "mechanical toolbox" icon_state = "blue" item_state = "toolbox_blue" - material_flags = NONE /obj/item/storage/toolbox/mechanical/PopulateContents() new /obj/item/screwdriver(src) @@ -102,7 +105,6 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) name = "electrical toolbox" icon_state = "yellow" item_state = "toolbox_yellow" - material_flags = NONE /obj/item/storage/toolbox/electrical/PopulateContents() var/pickedcolor = pick("red","yellow","green","blue","pink","orange","cyan","white") @@ -124,7 +126,6 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) desc = "A toolbox painted black with a red stripe. It looks more heavier than normal toolboxes." force = 15 throwforce = 18 - material_flags = NONE /obj/item/storage/toolbox/syndicate/ComponentInitialize() . = ..() @@ -144,7 +145,6 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) name = "mechanical toolbox" icon_state = "blue" item_state = "toolbox_blue" - material_flags = NONE /obj/item/storage/toolbox/drone/PopulateContents() var/pickedcolor = pick("red","yellow","green","blue","pink","orange","cyan","white") @@ -166,7 +166,6 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) w_class = WEIGHT_CLASS_HUGE attack_verb = list("robusted", "crushed", "smashed") can_rubberify = FALSE - material_flags = NONE var/fabricator_type = /obj/item/clockwork/replica_fabricator/scarab /obj/item/storage/toolbox/brass/ComponentInitialize() @@ -209,7 +208,6 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) w_class = WEIGHT_CLASS_HUGE //heyo no bohing this! force = 18 //spear damage can_rubberify = FALSE - material_flags = NONE /obj/item/storage/toolbox/plastitanium/afterattack(atom/A, mob/user, proximity) . = ..() @@ -225,7 +223,6 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) icon_state = "green" item_state = "toolbox_green" w_class = WEIGHT_CLASS_GIGANTIC //Holds more than a regular toolbox! - material_flags = NONE /obj/item/storage/toolbox/artistic/ComponentInitialize() . = ..() @@ -302,7 +299,6 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) icon_state = "gold" item_state = "toolbox_gold" has_latches = FALSE - material_flags = NONE /obj/item/storage/toolbox/gold_real/PopulateContents() new /obj/item/screwdriver/nuke(src) @@ -328,7 +324,6 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) force = 0 throwforce = 0 can_rubberify = FALSE - material_flags = NONE /obj/item/storage/toolbox/proc/rubberify() name = "rubber [name]" @@ -364,7 +359,6 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) throwforce = 15 attack_verb = list("robusted", "bounced") can_rubberify = FALSE //we are already the future. - material_flags = NONE /obj/item/storage/toolbox/rubber/Initialize() icon_state = pick("blue", "red", "yellow", "green") diff --git a/code/game/objects/items/storage/wallets.dm b/code/game/objects/items/storage/wallets.dm index 3aa9911d97..0b4b6f54f3 100644 --- a/code/game/objects/items/storage/wallets.dm +++ b/code/game/objects/items/storage/wallets.dm @@ -16,6 +16,7 @@ STR.cant_hold = typecacheof(list(/obj/item/screwdriver/power)) STR.can_hold = typecacheof(list( /obj/item/stack/spacecash, + /obj/item/holochip, /obj/item/card, /obj/item/clothing/mask/cigarette, /obj/item/flashlight/pen, @@ -101,17 +102,5 @@ icon_state = "random_wallet" /obj/item/storage/wallet/random/PopulateContents() - var/item1_type = /obj/effect/spawner/lootdrop/space_cash/no_turf - var/item2_type - if(prob(50)) - item2_type = /obj/effect/spawner/lootdrop/space_cash/no_turf - var/item3_type = /obj/effect/spawner/lootdrop/coin/no_turf - - spawn(2) - if(item1_type) - new item1_type(src) - if(item2_type) - new item2_type(src) - if(item3_type) - new item3_type(src) - update_icon() + new /obj/item/holochip(src, rand(5,30)) + icon_state = "wallet" diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm index 0fc47f649a..e9364bcede 100644 --- a/code/game/objects/items/stunbaton.dm +++ b/code/game/objects/items/stunbaton.dm @@ -16,7 +16,7 @@ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80) var/stamforce = 35 - var/status = FALSE + var/turned_on = FALSE var/knockdown = TRUE var/obj/item/stock_parts/cell/cell var/hitcost = 750 @@ -49,7 +49,7 @@ /obj/item/melee/baton/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() //Only mob/living types have stun handling - if(status && prob(throw_hit_chance) && iscarbon(hit_atom)) + if(turned_on && prob(throw_hit_chance) && iscarbon(hit_atom)) baton_stun(hit_atom) /obj/item/melee/baton/loaded //this one starts with a cell pre-installed. @@ -66,16 +66,16 @@ copper_top.use(min(chrgdeductamt, copper_top.charge), explode) if(QDELETED(src)) return FALSE - if(status && (!copper_top || !copper_top.charge || (chargecheck && copper_top.charge < (hitcost * STUNBATON_CHARGE_LENIENCY)))) + if(turned_on && (!copper_top || !copper_top.charge || (chargecheck && copper_top.charge < (hitcost * STUNBATON_CHARGE_LENIENCY)))) //we're below minimum, turn off switch_status(FALSE) /obj/item/melee/baton/proc/switch_status(new_status = FALSE, silent = FALSE) - if(status != new_status) - status = new_status + if(turned_on != new_status) + turned_on = new_status if(!silent) playsound(loc, "sparks", 75, 1, -1) - if(status) + if(turned_on) START_PROCESSING(SSobj, src) else STOP_PROCESSING(SSobj, src) @@ -85,7 +85,7 @@ deductcharge(round(hitcost * STUNBATON_DEPLETION_RATE), FALSE, FALSE) /obj/item/melee/baton/update_icon_state() - if(status) + if(turned_on) icon_state = "[initial(name)]_active" else if(!cell) icon_state = "[initial(name)]_nocell" @@ -134,8 +134,8 @@ else to_chat(user, "[src] is out of charge.") else - switch_status(!status) - to_chat(user, "[src] is now [status ? "on" : "off"].") + switch_status(!turned_on) + to_chat(user, "[src] is now [turned_on ? "on" : "off"].") add_fingerprint(user) /obj/item/melee/baton/attack(mob/M, mob/living/carbon/human/user) @@ -151,7 +151,7 @@ /obj/item/melee/baton/proc/common_baton_melee(mob/M, mob/living/user, disarming = FALSE) if(iscyborg(M) || !isliving(M)) //can't baton cyborgs return FALSE - if(status && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) + if(turned_on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) clowning_around(user) if(IS_STAMCRIT(user)) //CIT CHANGE - makes it impossible to baton in stamina softcrit to_chat(user, "You're too exhausted for that.") @@ -160,17 +160,17 @@ var/mob/living/carbon/human/L = M if(check_martial_counter(L, user)) return TRUE - if(status) + if(turned_on) if(baton_stun(M, user, disarming)) user.do_attack_animation(M) - user.adjustStaminaLossBuffered(getweight()) //CIT CHANGE - makes stunbatonning others cost stamina + user.adjustStaminaLossBuffered(getweight(user, STAM_COST_BATON_MOB_MULT)) else if(user.a_intent != INTENT_HARM) //they'll try to bash in the last proc. M.visible_message("[user] has prodded [M] with [src]. Luckily it was off.", \ "[user] has prodded you with [src]. Luckily it was off") return disarming || (user.a_intent != INTENT_HARM) /obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/user, disarming = FALSE) - if(L.run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user) & BLOCK_SUCCESS) //No message; check_shields() handles that + if(L.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, null) & BLOCK_SUCCESS) //No message; check_shields() handles that playsound(L, 'sound/weapons/genhit.ogg', 50, 1) return FALSE var/stunpwr = stamforce @@ -232,11 +232,8 @@ /obj/item/melee/baton/stunsword name = "stunsword" desc = "not actually sharp, this sword is functionally identical to a stunbaton" - icon = 'modular_citadel/icons/obj/stunsword.dmi' icon_state = "stunsword" item_state = "sword" - lefthand_file = 'modular_citadel/icons/mob/inhands/stunsword_left.dmi' - righthand_file = 'modular_citadel/icons/mob/inhands/stunsword_right.dmi' /obj/item/melee/baton/stunsword/get_belt_overlay() if(istype(loc, /obj/item/storage/belt/sabre)) @@ -295,6 +292,48 @@ sparkler?.activate() . = ..() +/obj/item/melee/baton/boomerang + name = "\improper OZtek Boomerang" + desc = "A device invented in 2486 for the great Space Emu War by the confederacy of Australicus, these high-tech boomerangs also work exceptionally well at stunning crewmembers. Just be careful to catch it when thrown!" + throw_speed = 1 + icon_state = "boomerang" + item_state = "boomerang" + force = 5 + throwforce = 5 + throw_range = 5 + hitcost = 2000 + throw_hit_chance = 99 //Have you prayed today? + custom_materials = list(/datum/material/iron = 10000, /datum/material/glass = 4000, /datum/material/silver = 10000, /datum/material/gold = 2000) + +/obj/item/melee/baton/boomerang/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force) + if(turned_on) + if(ishuman(thrower)) + var/mob/living/carbon/human/H = thrower + H.throw_mode_off() //so they can catch it on the return. + return ..() + +/obj/item/melee/baton/boomerang/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + if(turned_on) + var/caught = hit_atom.hitby(src, FALSE, FALSE, throwingdatum=throwingdatum) + if(ishuman(hit_atom) && !caught && prob(throw_hit_chance))//if they are a carbon and they didn't catch it + baton_stun(hit_atom) + if(thrownby && !caught) + sleep(1) + if(!QDELETED(src)) + throw_at(thrownby, throw_range+2, throw_speed, null, TRUE) + else + return ..() + +/obj/item/melee/baton/boomerang/update_icon() + if(turned_on) + icon_state = "[initial(icon_state)]_active" + else if(!cell) + icon_state = "[initial(icon_state)]_nocell" + else + icon_state = "[initial(icon_state)]" + +/obj/item/melee/baton/boomerang/loaded //Same as above, comes with a cell. + preload_cell_type = /obj/item/stock_parts/cell/high #undef STUNBATON_CHARGE_LENIENCY #undef STUNBATON_DEPLETION_RATE diff --git a/code/game/objects/items/tanks/watertank.dm b/code/game/objects/items/tanks/watertank.dm index 6ff5dfc8ad..de5f332f43 100644 --- a/code/game/objects/items/tanks/watertank.dm +++ b/code/game/objects/items/tanks/watertank.dm @@ -145,6 +145,7 @@ desc = "A janitorial watertank backpack with nozzle to clean dirt and graffiti." icon_state = "waterbackpackjani" item_state = "waterbackpackjani" + custom_price = 1000 /obj/item/watertank/janitor/Initialize() . = ..() @@ -209,6 +210,7 @@ power = 8 force = 10 precision = 1 + total_mass = 0.2 cooling_power = 5 w_class = WEIGHT_CLASS_HUGE item_flags = ABSTRACT // don't put in storage diff --git a/code/game/objects/items/teleportation.dm b/code/game/objects/items/teleportation.dm index b5edb27704..881e4d5f1a 100644 --- a/code/game/objects/items/teleportation.dm +++ b/code/game/objects/items/teleportation.dm @@ -104,7 +104,7 @@ if (ismob(src.loc)) attack_self(src.loc) else - for(var/mob/M in viewers(1, src)) + for(var/mob/M in fov_viewers(1, src)) if (M.client) src.attack_self(M) return diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 9291b72467..ff59b85332 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -241,11 +241,13 @@ playsound(user, activation_sound, transform_volume, 1) w_class = WEIGHT_CLASS_BULKY AddElement(/datum/element/sword_point) + total_mass = total_mass_on else to_chat(user, "[deactivation_message]") playsound(user, deactivation_sound, transform_volume, 1) w_class = WEIGHT_CLASS_SMALL RemoveElement(/datum/element/sword_point) + total_mass = initial(total_mass) update_icon() add_fingerprint(user) @@ -287,9 +289,6 @@ else return ..() -/obj/item/toy/sword/getweight() - return (active ? total_mass_on : total_mass) || w_class *1.25 - /obj/item/toy/sword/cx name = "\improper DX Non-Euplastic LightSword" desc = "A deluxe toy replica of an energy sword. Realistic visuals and sounds! Ages 8 and up." @@ -903,79 +902,57 @@ name = "hand of cards" desc = "A number of cards not in a deck, customarily held in ones hand." icon = 'icons/obj/toy.dmi' - icon_state = "nanotrasen_hand2" + icon_state = "none" w_class = WEIGHT_CLASS_TINY var/list/currenthand = list() var/choice = null - /obj/item/toy/cards/cardhand/attack_self(mob/user) - user.set_machine(src) + var/list/handradial = list() interact(user) -/obj/item/toy/cards/cardhand/ui_interact(mob/user) - . = ..() - var/dat = "You have:
" for(var/t in currenthand) - dat += "A [t].
" - dat += "Which card will you remove next?" - var/datum/browser/popup = new(user, "cardhand", "Hand of Cards", 400, 240) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.set_content(dat) - popup.open() + handradial[t] = image(icon = src.icon, icon_state = "sc_[t]_[deckstyle]") - -/obj/item/toy/cards/cardhand/Topic(href, href_list) - if(..()) - return if(usr.stat || !ishuman(usr)) return var/mob/living/carbon/human/cardUser = usr - var/O = src - if(href_list["pick"]) - if (cardUser.is_holding(src)) - var/choice = href_list["pick"] - var/obj/item/toy/cards/singlecard/C = new/obj/item/toy/cards/singlecard(cardUser.loc) - src.currenthand -= choice - C.parentdeck = src.parentdeck - C.cardname = choice - C.apply_card_vars(C,O) - C.pickup(cardUser) - cardUser.put_in_hands(C) - cardUser.visible_message("[cardUser] draws a card from [cardUser.p_their()] hand.", "You take the [C.cardname] from your hand.") - - interact(cardUser) - if(src.currenthand.len < 3) - src.icon_state = "[deckstyle]_hand2" - else if(src.currenthand.len < 4) - src.icon_state = "[deckstyle]_hand3" - else if(src.currenthand.len < 5) - src.icon_state = "[deckstyle]_hand4" - if(src.currenthand.len == 1) - var/obj/item/toy/cards/singlecard/N = new/obj/item/toy/cards/singlecard(src.loc) - N.parentdeck = src.parentdeck - N.cardname = src.currenthand[1] - N.apply_card_vars(N,O) - qdel(src) - N.pickup(cardUser) - cardUser.put_in_hands(N) - to_chat(cardUser, "You also take [currenthand[1]] and hold it.") - cardUser << browse(null, "window=cardhand") + if(!(cardUser.mobility_flags & MOBILITY_USE)) return + var/O = src + var/choice = show_radial_menu(usr,src, handradial, custom_check = CALLBACK(src, .proc/check_menu, user), radius = 36, require_near = TRUE) + if(!choice) + return FALSE + var/obj/item/toy/cards/singlecard/C = new/obj/item/toy/cards/singlecard(cardUser.loc) + currenthand -= choice + handradial -= choice + C.parentdeck = parentdeck + C.cardname = choice + C.apply_card_vars(C,O) + C.pickup(cardUser) + cardUser.put_in_hands(C) + cardUser.visible_message("[cardUser] draws a card from [cardUser.p_their()] hand.", "You take the [C.cardname] from your hand.") + + interact(cardUser) + update_sprite() + if(length(currenthand) == 1) + var/obj/item/toy/cards/singlecard/N = new/obj/item/toy/cards/singlecard(loc) + N.parentdeck = parentdeck + N.cardname = currenthand[1] + N.apply_card_vars(N,O) + qdel(src) + N.pickup(cardUser) + cardUser.put_in_hands(N) + to_chat(cardUser, "You also take [currenthand[1]] and hold it.") /obj/item/toy/cards/cardhand/attackby(obj/item/toy/cards/singlecard/C, mob/living/user, params) if(istype(C)) if(C.parentdeck == src.parentdeck) src.currenthand += C.cardname - user.visible_message("[user] adds a card to [user.p_their()] hand.", "You add the [C.cardname] to your hand.") + user.visible_message("[user] adds a card to [user.p_their()] hand.", "You add the [C.cardname] to your hand.") qdel(C) interact(user) - if(currenthand.len > 4) - src.icon_state = "[deckstyle]_hand5" - else if(currenthand.len > 3) - src.icon_state = "[deckstyle]_hand4" - else if(currenthand.len > 2) - src.icon_state = "[deckstyle]_hand3" + update_sprite(src) else to_chat(user, "You can't mix cards from other decks!") else @@ -984,7 +961,7 @@ /obj/item/toy/cards/cardhand/apply_card_vars(obj/item/toy/cards/newobj,obj/item/toy/cards/sourceobj) ..() newobj.deckstyle = sourceobj.deckstyle - newobj.icon_state = "[deckstyle]_hand2" // Another dumb hack, without this the hand is invisible (or has the default deckstyle) until another card is added. + update_sprite() newobj.card_hitsound = sourceobj.card_hitsound newobj.card_force = sourceobj.card_force newobj.card_throwforce = sourceobj.card_throwforce @@ -993,6 +970,31 @@ newobj.card_attack_verb = sourceobj.card_attack_verb newobj.resistance_flags = sourceobj.resistance_flags +/** + * check_menu: Checks if we are allowed to interact with a radial menu + * + * Arguments: + * * user The mob interacting with a menu + */ +/obj/item/toy/cards/cardhand/proc/check_menu(mob/living/user) + if(!istype(user)) + return FALSE + if(user.incapacitated()) + return FALSE + return TRUE + +/** + * This proc updates the sprite for when you create a hand of cards + */ +/obj/item/toy/cards/cardhand/proc/update_sprite() + cut_overlays() + var/overlay_cards = currenthand.len + + var/k = overlay_cards == 2 ? 1 : overlay_cards - 2 + for(var/i = k; i <= overlay_cards; i++) + var/card_overlay = image(icon=src.icon,icon_state="sc_[currenthand[i]]_[deckstyle]",pixel_x=(1-i+k)*3,pixel_y=(1-i+k)*3) + add_overlay(card_overlay) + /obj/item/toy/cards/singlecard name = "card" desc = "a card" diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index 2b6a91eb51..acfc9a6e85 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -1182,7 +1182,7 @@ if(iscyborg(target)) ..() return - if(target.run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user) & BLOCK_SUCCESS) //No message; run_block() handles that + if(target.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, null) & BLOCK_SUCCESS) //No message; run_block() handles that playsound(target, 'sound/weapons/genhit.ogg', 50, 1) return FALSE if(user.a_intent != INTENT_HARM) diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 2d132e4eef..aa0aa70e03 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -478,6 +478,20 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 throw_range = 2 attack_verb = list("busted") +/obj/item/statuebust/attack_self(mob/living/user) + add_fingerprint(user) + user.examinate(src) + +/obj/item/statuebust/examine(mob/living/user) + . = ..() + if(.) + return + if (!isliving(user)) + return + user.visible_message("[user] stops to admire [src].", \ + "You take in [src], admiring its fine craftsmanship.") + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artgood", /datum/mood_event/artgood) + /obj/item/tailclub name = "tail club" desc = "For the beating to death of lizards with their own tails." @@ -524,6 +538,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 icon_state = "skateboard2" item_state = "skateboard2" board_item_type = /obj/vehicle/ridden/scooter/skateboard/pro + custom_premium_price = 500 /obj/item/melee/skateboard/hoverboard name = "hoverboard" @@ -531,6 +546,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 icon_state = "hoverboard_red" item_state = "hoverboard_red" board_item_type = /obj/vehicle/ridden/scooter/skateboard/hoverboard + custom_premium_price = 2015 /obj/item/melee/skateboard/hoverboard/admin name = "\improper Board Of Directors" diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 8dac972d04..e64b7d8f8d 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -112,7 +112,7 @@ /obj/attack_animal(mob/living/simple_animal/M) if(!M.melee_damage_upper && !M.obj_damage) - M.emote("custom", message = "[M.friendly] [src].") + M.emote("custom", message = "[M.friendly_verb_continuous] [src].") return 0 else var/play_soundeffect = 1 @@ -232,15 +232,16 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e cut_overlay(GLOB.fire_overlay, TRUE) SSfire_burning.processing -= src -/obj/proc/tesla_act(power, tesla_flags, shocked_targets) +/obj/zap_act(power, zap_flags, shocked_targets) + if(QDELETED(src)) + return 0 obj_flags |= BEING_SHOCKED - var/power_bounced = power / 2 - tesla_zap(src, 3, power_bounced, tesla_flags, shocked_targets) addtimer(CALLBACK(src, .proc/reset_shocked), 10) + return power / 2 //The surgeon general warns that being buckled to certain objects receiving powerful shocks is greatly hazardous to your health -//Only tesla coils and grounding rods currently call this because mobs are already targeted over all other objects, but this might be useful for more things later. -/obj/proc/tesla_buckle_check(var/strength) +//Only tesla coils, vehicles, and grounding rods currently call this because mobs are already targeted over all other objects, but this might be useful for more things later. +/obj/proc/zap_buckle_check(var/strength) if(has_buckled_mobs()) for(var/m in buckled_mobs) var/mob/living/buckled_mob = m diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 199f0c51e2..0b2fe5ac2a 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -123,7 +123,7 @@ /obj/proc/updateUsrDialog() if((obj_flags & IN_USE) && !(obj_flags & USES_TGUI)) var/is_in_use = FALSE - var/list/nearby = viewers(1, src) + var/list/nearby = fov_viewers(1, src) for(var/mob/M in nearby) if ((M.client && M.machine == src)) is_in_use = TRUE @@ -152,7 +152,7 @@ if(obj_flags & IN_USE) var/is_in_use = FALSE if(update_viewers) - for(var/mob/M in viewers(1, src)) + for(var/mob/M in fov_viewers(1, src)) if ((M.client && M.machine == src)) is_in_use = TRUE src.interact(M) diff --git a/code/game/objects/structures/ai_core.dm b/code/game/objects/structures/ai_core.dm index 3e35c12314..1090bae9f8 100644 --- a/code/game/objects/structures/ai_core.dm +++ b/code/game/objects/structures/ai_core.dm @@ -131,7 +131,7 @@ if(C.get_amount() >= 5) playsound(loc, 'sound/items/deconstruct.ogg', 50, 1) to_chat(user, "You start to add cables to the frame...") - if(do_after(user, 20, target = src) && state == SCREWED_CORE && C.use(5)) + if(do_after(user, 20, target = src) && state == SCREWED_CORE && C.use_tool(src, user, 0, 5)) to_chat(user, "You add cables to the frame.") state = CABLED_CORE update_icon() diff --git a/code/game/objects/structures/artstuff.dm b/code/game/objects/structures/artstuff.dm index 405e697d3b..98f772a116 100644 --- a/code/game/objects/structures/artstuff.dm +++ b/code/game/objects/structures/artstuff.dm @@ -35,101 +35,368 @@ else painting = null - -////////////// -// CANVASES // -////////////// - -#define AMT_OF_CANVASES 4 //Keep this up to date or shit will break. - -//To safe memory on making /icons we cache the blanks.. -GLOBAL_LIST_INIT(globalBlankCanvases, new(AMT_OF_CANVASES)) - /obj/item/canvas name = "canvas" desc = "Draw out your soul on this canvas!" icon = 'icons/obj/artstuff.dmi' icon_state = "11x11" resistance_flags = FLAMMABLE - var/whichGlobalBackup = 1 //List index + var/width = 11 + var/height = 11 + var/list/grid + var/canvas_color = "#ffffff" //empty canvas color + var/ui_x = 400 + var/ui_y = 400 + var/used = FALSE + var/painting_name //Painting name, this is set after framing. + var/finalized = FALSE //Blocks edits + var/author_ckey + var/icon_generated = FALSE + var/icon/generated_icon -/obj/item/canvas/nineteenXnineteen - icon_state = "19x19" - whichGlobalBackup = 2 + // Painting overlay offset when framed + var/framed_offset_x = 11 + var/framed_offset_y = 10 -/obj/item/canvas/twentythreeXnineteen - icon_state = "23x19" - whichGlobalBackup = 3 + pixel_x = 10 + pixel_y = 9 -/obj/item/canvas/twentythreeXtwentythree - icon_state = "23x23" - whichGlobalBackup = 4 - -//HEY YOU -//ARE YOU READING THE CODE FOR CANVASES? -//ARE YOU AWARE THEY CRASH HALF THE SERVER WHEN SOMEONE DRAWS ON THEM... -//...AND NOBODY CAN FIGURE OUT WHY? -//THEN GO ON BRAVE TRAVELER -//TRY TO FIX THEM AND REMOVE THIS CODE /obj/item/canvas/Initialize() - ..() - return INITIALIZE_HINT_QDEL //Delete on creation + . = ..() + reset_grid() -//Find the right size blank canvas -/obj/item/canvas/proc/getGlobalBackup() - . = null - if(GLOB.globalBlankCanvases[whichGlobalBackup]) - . = GLOB.globalBlankCanvases[whichGlobalBackup] - else - var/icon/I = icon(initial(icon),initial(icon_state)) - GLOB.globalBlankCanvases[whichGlobalBackup] = I - . = I +/obj/item/canvas/proc/reset_grid() + grid = new/list(width,height) + for(var/x in 1 to width) + for(var/y in 1 to height) + grid[x][y] = canvas_color +/obj/item/canvas/attack_self(mob/user) + . = ..() + ui_interact(user) +/obj/item/canvas/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ + datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) -//One pixel increments -/obj/item/canvas/attackby(obj/item/I, mob/user, params) - //Click info - var/list/click_params = params2list(params) - var/pixX = text2num(click_params["icon-x"]) - var/pixY = text2num(click_params["icon-y"]) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "canvas", name, ui_x, ui_y, master_ui, state) + ui.set_autoupdate(FALSE) + ui.open() - //Should always be true, otherwise you didn't click the object, but let's check because SS13~ - if(!click_params || !click_params["icon-x"] || !click_params["icon-y"]) - return - - //Cleaning one pixel with a soap or rag - if(istype(I, /obj/item/soap) || istype(I, /obj/item/reagent_containers/rag)) - //Pixel info created only when needed - var/icon/masterpiece = icon(icon,icon_state) - var/thePix = masterpiece.GetPixel(pixX,pixY) - var/icon/Ico = getGlobalBackup() - if(!Ico) - qdel(masterpiece) - return - - var/theOriginalPix = Ico.GetPixel(pixX,pixY) - if(thePix != theOriginalPix) //colour changed - DrawPixelOn(theOriginalPix,pixX,pixY) - qdel(masterpiece) - - //Drawing one pixel with a crayon - else if(istype(I, /obj/item/toy/crayon)) - var/obj/item/toy/crayon/C = I - DrawPixelOn(C.paint_color, pixX, pixY) +/obj/item/canvas/attackby(obj/item/I, mob/living/user, params) + if(user.a_intent == INTENT_HELP) + ui_interact(user) else return ..() +/obj/item/canvas/ui_data(mob/user) + . = ..() + .["grid"] = grid + .["name"] = painting_name + .["finalized"] = finalized -//Clean the whole canvas -/obj/item/canvas/attack_self(mob/user) - if(!user) +/obj/item/canvas/examine(mob/user) + . = ..() + ui_interact(user) + +/obj/item/canvas/ui_act(action, params) + . = ..() + if(. || finalized) return - var/icon/blank = getGlobalBackup() - if(blank) - //it's basically a giant etch-a-sketch - icon = blank - user.visible_message("[user] cleans the canvas.","You clean the canvas.") + var/mob/user = usr + switch(action) + if("paint") + var/obj/item/I = user.get_active_held_item() + var/color = get_paint_tool_color(I) + if(!color) + return FALSE + var/x = text2num(params["x"]) + var/y = text2num(params["y"]) + grid[x][y] = color + used = TRUE + update_icon() + . = TRUE + if("finalize") + . = TRUE + if(!finalized) + finalize(user) + +/obj/item/canvas/proc/finalize(mob/user) + finalized = TRUE + author_ckey = user.ckey + generate_proper_overlay() + try_rename(user) + +/obj/item/canvas/update_overlays() + . = ..() + if(!icon_generated) + if(used) + var/mutable_appearance/detail = mutable_appearance(icon,"[icon_state]wip") + detail.pixel_x = 1 + detail.pixel_y = 1 + . += detail + else + var/mutable_appearance/detail = mutable_appearance(generated_icon) + detail.pixel_x = 1 + detail.pixel_y = 1 + . += detail + +/obj/item/canvas/proc/generate_proper_overlay() + if(icon_generated) + return + var/png_filename = "data/paintings/temp_painting.png" + var/result = rustg_dmi_create_png(png_filename,"[width]","[height]",get_data_string()) + if(result) + CRASH("Error generating painting png : [result]") + generated_icon = new(png_filename) + icon_generated = TRUE + update_icon() + +/obj/item/canvas/proc/get_data_string() + var/list/data = list() + for(var/y in 1 to height) + for(var/x in 1 to width) + data += grid[x][y] + return data.Join("") + +//Todo make this element ? +/obj/item/canvas/proc/get_paint_tool_color(obj/item/I) + if(!I) + return + if(istype(I, /obj/item/toy/crayon)) + var/obj/item/toy/crayon/C = I + return C.paint_color + else if(istype(I, /obj/item/pen)) + var/obj/item/pen/P = I + switch(P.colour) + if("black") + return "#000000" + if("blue") + return "#0000ff" + if("red") + return "#ff0000" + return P.colour + else if(istype(I, /obj/item/soap) || istype(I, /obj/item/reagent_containers/rag)) + return canvas_color + +/obj/item/canvas/proc/try_rename(mob/user) + var/new_name = stripped_input(user,"What do you want to name the painting?") + if(!painting_name && new_name && user.canUseTopic(src,BE_CLOSE)) + painting_name = new_name + SStgui.update_uis(src) + +/obj/item/canvas/nineteenXnineteen + icon_state = "19x19" + width = 19 + height = 19 + ui_x = 600 + ui_y = 600 + pixel_x = 6 + pixel_y = 9 + framed_offset_x = 8 + framed_offset_y = 9 + +/obj/item/canvas/twentythreeXnineteen + icon_state = "23x19" + width = 23 + height = 19 + ui_x = 800 + ui_y = 600 + pixel_x = 4 + pixel_y = 10 + framed_offset_x = 6 + framed_offset_y = 8 + +/obj/item/canvas/twentythreeXtwentythree + icon_state = "23x23" + width = 23 + height = 23 + ui_x = 800 + ui_y = 800 + pixel_x = 5 + pixel_y = 9 + framed_offset_x = 5 + framed_offset_y = 6 + +/obj/item/wallframe/painting + name = "painting frame" + desc = "The perfect showcase for your favorite deathtrap memories." + icon = 'icons/obj/decals.dmi' + custom_materials = null + flags_1 = 0 + icon_state = "frame-empty" + result_path = /obj/structure/sign/painting + +/obj/structure/sign/painting + name = "Painting" + desc = "Art or \"Art\"? You decide." + icon = 'icons/obj/decals.dmi' + icon_state = "frame-empty" + buildable_sign = FALSE + var/obj/item/canvas/C + var/persistence_id + +/obj/structure/sign/painting/Initialize(mapload, dir, building) + . = ..() + SSpersistence.painting_frames += src + AddComponent(/datum/component/art, 20) + if(dir) + setDir(dir) + if(building) + pixel_x = (dir & 3)? 0 : (dir == 4 ? -30 : 30) + pixel_y = (dir & 3)? (dir ==1 ? -30 : 30) : 0 + +/obj/structure/sign/painting/Destroy() + . = ..() + SSpersistence.painting_frames -= src + +/obj/structure/sign/painting/attackby(obj/item/I, mob/user, params) + if(!C && istype(I, /obj/item/canvas)) + frame_canvas(user,I) + else if(C && !C.painting_name && istype(I,/obj/item/pen)) + try_rename(user) + else + return ..() + +/obj/structure/sign/painting/examine(mob/user) + . = ..() + if(C) + C.ui_interact(user,state = GLOB.physical_obscured_state) + +/obj/structure/sign/painting/wirecutter_act(mob/living/user, obj/item/I) + . = ..() + if(C) + C.forceMove(drop_location()) + C = null + to_chat(user, "You remove the painting from the frame.") + update_icon() + return TRUE + +/obj/structure/sign/painting/proc/frame_canvas(mob/user,obj/item/canvas/new_canvas) + if(user.transferItemToLoc(new_canvas,src)) + C = new_canvas + if(!C.finalized) + C.finalize(user) + to_chat(user,"You frame [C].") + update_icon() + +/obj/structure/sign/painting/proc/try_rename(mob/user) + if(!C.painting_name) + C.try_rename(user) + +/obj/structure/sign/painting/update_icon_state() + . = ..() + if(C && C.generated_icon) + icon_state = null + else + icon_state = "frame-empty" -#undef AMT_OF_CANVASES +/obj/structure/sign/painting/update_overlays() + . = ..() + if(C && C.generated_icon) + var/mutable_appearance/MA = mutable_appearance(C.generated_icon) + MA.pixel_x = C.framed_offset_x + MA.pixel_y = C.framed_offset_y + . += MA + var/mutable_appearance/frame = mutable_appearance(C.icon,"[C.icon_state]frame") + frame.pixel_x = C.framed_offset_x - 1 + frame.pixel_y = C.framed_offset_y - 1 + . += frame + +/obj/structure/sign/painting/proc/load_persistent() + if(!persistence_id) + return + if(!SSpersistence.paintings || !SSpersistence.paintings[persistence_id] || !length(SSpersistence.paintings[persistence_id])) + return + var/list/chosen = pick(SSpersistence.paintings[persistence_id]) + var/title = chosen["title"] + var/author = chosen["ckey"] + var/png = "data/paintings/[persistence_id]/[chosen["md5"]].png" + if(!fexists(png)) + stack_trace("Persistent painting [chosen["md5"]].png was not found in [persistence_id] directory.") + return + var/icon/I = new(png) + var/obj/item/canvas/new_canvas + var/w = I.Width() + var/h = I.Height() + for(var/T in typesof(/obj/item/canvas)) + new_canvas = T + if(initial(new_canvas.width) == w && initial(new_canvas.height) == h) + new_canvas = new T(src) + break + new_canvas.fill_grid_from_icon(I) + new_canvas.generated_icon = I + new_canvas.icon_generated = TRUE + new_canvas.finalized = TRUE + new_canvas.painting_name = title + new_canvas.author_ckey = author + C = new_canvas + update_icon() + +/obj/structure/sign/painting/proc/save_persistent() + if(!persistence_id || !C) + return + if(sanitize_filename(persistence_id) != persistence_id) + stack_trace("Invalid persistence_id - [persistence_id]") + return + var/data = C.get_data_string() + var/md5 = md5(data) + var/list/current = SSpersistence.paintings[persistence_id] + if(!current) + current = list() + for(var/list/entry in current) + if(entry["md5"] == md5) + return + var/png_directory = "data/paintings/[persistence_id]/" + var/png_path = png_directory + "[md5].png" + var/result = rustg_dmi_create_png(png_path,"[C.width]","[C.height]",data) + if(result) + CRASH("Error saving persistent painting: [result]") + current += list(list("title" = C.painting_name , "md5" = md5, "ckey" = C.author_ckey)) + SSpersistence.paintings[persistence_id] = current + +/obj/item/canvas/proc/fill_grid_from_icon(icon/I) + var/h = I.Height() + 1 + for(var/x in 1 to width) + for(var/y in 1 to height) + grid[x][y] = I.GetPixel(x,h-y) + +//Presets for art gallery mapping, for paintings to be shared across stations +/obj/structure/sign/painting/library + persistence_id = "library" + +/obj/structure/sign/painting/library_secure + persistence_id = "library_secure" + +/obj/structure/sign/painting/library_private // keep your smut away from prying eyes, or non-librarians at least + persistence_id = "library_private" + +/obj/structure/sign/painting/vv_get_dropdown() + . = ..() + VV_DROPDOWN_OPTION(VV_HK_REMOVE_PAINTING, "Remove Persistent Painting") + +/obj/structure/sign/painting/vv_do_topic(list/href_list) + . = ..() + if(href_list[VV_HK_REMOVE_PAINTING]) + if(!check_rights(NONE)) + return + var/mob/user = usr + if(!persistence_id || !C) + to_chat(user,"This is not a persistent painting.") + return + var/md5 = md5(C.get_data_string()) + var/author = C.author_ckey + var/list/current = SSpersistence.paintings[persistence_id] + if(current) + for(var/list/entry in current) + if(entry["md5"] == md5) + current -= entry + var/png = "data/paintings/[persistence_id]/[md5].png" + fdel(png) + for(var/obj/structure/sign/painting/P in SSpersistence.painting_frames) + if(P.C && md5(P.C.get_data_string()) == md5) + QDEL_NULL(P.C) + log_admin("[key_name(user)] has deleted a persistent painting made by [author].") + message_admins("[key_name_admin(user)] has deleted persistent painting made by [author].") diff --git a/code/game/objects/structures/barsigns.dm b/code/game/objects/structures/barsigns.dm index d2fff9649d..821409c26b 100644 --- a/code/game/objects/structures/barsigns.dm +++ b/code/game/objects/structures/barsigns.dm @@ -84,7 +84,6 @@ panel_open = FALSE else if(istype(I, /obj/item/stack/cable_coil) && panel_open) - var/obj/item/stack/cable_coil/C = I if(obj_flags & EMAGGED) //Emagged, not broken by EMP to_chat(user, "Sign has been damaged beyond repair!") return @@ -92,7 +91,7 @@ to_chat(user, "This sign is functioning properly!") return - if(C.use(2)) + if(I.use_tool(src, user, 0, 2)) to_chat(user, "You replace the burnt wiring.") broken = FALSE else diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm index d3e8ecf0a6..2225c4c0c2 100644 --- a/code/game/objects/structures/beds_chairs/chair.dm +++ b/code/game/objects/structures/beds_chairs/chair.dm @@ -108,7 +108,9 @@ if(!istype(poordude)) return TRUE user.visible_message("[user] pulls [src] out from under [poordude].", "You pull [src] out from under [poordude].") - var/C = new item_chair(loc) + var/obj/item/chair/C = new item_chair(loc) + C.set_custom_materials(custom_materials) + TransferComponents(C) user.put_in_hands(C) poordude.DefaultCombatKnockdown(20)//rip in peace user.adjustStaminaLoss(5) diff --git a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm index ae2e1a070a..500b8d6a49 100644 --- a/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm +++ b/code/game/objects/structures/crates_lockers/closets/cardboardbox.dm @@ -24,6 +24,7 @@ move_delay = TRUE var/oldloc = loc step(src, direction) + user.setDir(direction) if(oldloc != loc) addtimer(CALLBACK(src, .proc/ResetMoveDelay), (use_mob_movespeed ? user.movement_delay() : CONFIG_GET(number/movedelay/walk_delay)) * move_speed_multiplier) else @@ -42,7 +43,7 @@ Snake = L break if(Snake) - alerted = viewers(7,src) + alerted = fov_viewers(world.view,src) ..() if(LAZYLEN(alerted)) egged = world.time + SNAKE_SPAM_TICKS diff --git a/code/game/objects/structures/crates_lockers/crates/secure.dm b/code/game/objects/structures/crates_lockers/crates/secure.dm index 4ac69253d3..2c923c1905 100644 --- a/code/game/objects/structures/crates_lockers/crates/secure.dm +++ b/code/game/objects/structures/crates_lockers/crates/secure.dm @@ -74,4 +74,43 @@ /obj/structure/closet/crate/secure/medical desc = "A secure medical crate." name = "medical crate" - icon_state = "medical_secure_crate" \ No newline at end of file + icon_state = "medical_secure_crate" + +/obj/structure/closet/crate/secure/owned + name = "private crate" + desc = "A crate cover designed to only open for who purchased its contents." + icon_state = "privatecrate" + var/datum/bank_account/buyer_account + var/privacy_lock = TRUE + +/obj/structure/closet/crate/secure/owned/examine(mob/user) + . = ..() + to_chat(user, "It's locked with a privacy lock, and can only be unlocked by the buyer's ID.") + +/obj/structure/closet/crate/secure/owned/Initialize(mapload, datum/bank_account/_buyer_account) + . = ..() + buyer_account = _buyer_account + +/obj/structure/closet/crate/secure/owned/togglelock(mob/living/user, silent) + if(privacy_lock) + if(!broken) + var/obj/item/card/id/id_card = user.get_idcard(TRUE) + if(id_card) + if(id_card.registered_account) + if(id_card.registered_account == buyer_account) + if(iscarbon(user)) + add_fingerprint(user) + locked = !locked + user.visible_message("[user] unlocks [src]'s privacy lock.", + "You unlock [src]'s privacy lock.") + privacy_lock = FALSE + update_icon() + else if(!silent) + to_chat(user, "Bank account does not match with buyer!") + else if(!silent) + to_chat(user, "No linked bank account detected!") + else if(!silent) + to_chat(user, "No ID detected!") + else if(!silent) + to_chat(user, "[src] is broken!") + else ..() diff --git a/code/game/objects/structures/extinguisher.dm b/code/game/objects/structures/extinguisher.dm index 9b736517be..3bc84deb4d 100644 --- a/code/game/objects/structures/extinguisher.dm +++ b/code/game/objects/structures/extinguisher.dm @@ -3,6 +3,7 @@ desc = "A small wall mounted cabinet designed to hold a fire extinguisher." icon = 'icons/obj/wallmounts.dmi' icon_state = "extinguisher_closed" + plane = ABOVE_WALL_PLANE anchored = TRUE density = FALSE max_integrity = 200 diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index e44698f96e..679a755321 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -7,6 +7,7 @@ anchored = TRUE icon = 'icons/turf/walls/wall.dmi' icon_state = "wall" + plane = WALL_PLANE layer = LOW_OBJ_LAYER density = TRUE opacity = 1 diff --git a/code/game/objects/structures/fireaxe.dm b/code/game/objects/structures/fireaxe.dm index 0f3a23dd0f..f4c1dd5ab9 100644 --- a/code/game/objects/structures/fireaxe.dm +++ b/code/game/objects/structures/fireaxe.dm @@ -3,6 +3,7 @@ desc = "There is a small label that reads \"For Emergency use only\" along with details for safe use of the axe. As if." icon = 'icons/obj/wallmounts.dmi' icon_state = "fireaxe" + plane = ABOVE_WALL_PLANE anchored = TRUE density = FALSE armor = list("melee" = 50, "bullet" = 20, "laser" = 0, "energy" = 100, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 50) diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index c0ee7bb987..e03ece2dfa 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -302,7 +302,7 @@ /obj/item/twohanded/required/kirbyplants/Initialize() . = ..() - AddComponent(/datum/component/tactical) + AddElement(/datum/element/tactical) /obj/item/twohanded/required/kirbyplants/random icon = 'icons/obj/flora/_flora.dmi' diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index e794e12ad7..86aff44e02 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -32,6 +32,7 @@ new_spawn.undershirt = "Nude" //changing underwear/shirt/socks doesn't seem to function correctly right now because of some bug elsewhere? new_spawn.socks = "Nude" new_spawn.update_body(TRUE) + new_spawn.language_holder.selected_language = /datum/language/sylvan //Ash walker eggs: Spawns in ash walker dens in lavaland. Ghosts become unbreathing lizards that worship the Necropolis and are advised to retrieve corpses to create more ash walkers. @@ -63,10 +64,6 @@ else to_chat(new_spawn, "You have been born outside of your natural home! Whether you decide to return home, or make due with your new home is your own decision.") - new_spawn.grant_language(/datum/language/draconic) - var/datum/language_holder/holder = new_spawn.get_language_holder() - holder.selected_default_language = /datum/language/draconic - //Ash walkers on birth understand how to make bone bows, bone arrows and ashen arrows new_spawn.mind.teach_crafting_recipe(/datum/crafting_recipe/bone_arrow) @@ -689,7 +686,7 @@ name = "ID, jumpsuit and shoes" uniform = /obj/item/clothing/under/color/random shoes = /obj/item/clothing/shoes/sneakers/black - id = /obj/item/card/id + id = /obj/item/card/id/no_banking r_hand = /obj/item/storage/box/syndie_kit/chameleon/ghostcafe diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index fd62ffd368..cacf361722 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -6,6 +6,7 @@ density = TRUE var/state = GIRDER_NORMAL var/girderpasschance = 20 // percentage chance that a projectile passes through the girder. + var/next_beep = 0 //Prevents spamming of the construction sound var/can_displace = TRUE //If the girder can be moved around by wrenching it max_integrity = 200 rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE @@ -27,11 +28,17 @@ . += "[src] is disassembled! You probably shouldn't be able to see this examine message." /obj/structure/girder/attackby(obj/item/W, mob/user, params) + var/platingmodifier = 1 + if(HAS_TRAIT(user, TRAIT_QUICK_BUILD)) + platingmodifier = 0.7 + if(next_beep <= world.time) + next_beep = world.time + 10 + playsound(src, 'sound/machines/clockcult/integration_cog_install.ogg', 50, TRUE) add_fingerprint(user) if(istype(W, /obj/item/gun/energy/plasmacutter)) to_chat(user, "You start slicing apart the girder...") - if(W.use_tool(src, user, 40, volume=100)) + if(W.use_tool(src, user, 40*platingmodifier, volume=100)) to_chat(user, "You slice apart the girder.") var/obj/item/stack/sheet/metal/M = new (loc, 2) M.add_fingerprint(user) @@ -62,7 +69,7 @@ to_chat(user, "You need at least two rods to create a false wall!") return to_chat(user, "You start building a reinforced false wall...") - if(do_after(user, 20, target = src)) + if(do_after(user, 20*platingmodifier, target = src)) if(S.get_amount() < 2) return S.use(2) @@ -75,7 +82,7 @@ to_chat(user, "You need at least five rods to add plating!") return to_chat(user, "You start adding plating...") - if(do_after(user, 40, target = src)) + if(do_after(user, 40*platingmodifier, target = src)) if(S.get_amount() < 5) return S.use(5) @@ -96,7 +103,7 @@ to_chat(user, "You need two sheets of metal to create a false wall!") return to_chat(user, "You start building a false wall...") - if(do_after(user, 20, target = src)) + if(do_after(user, 20*platingmodifier, target = src)) if(S.get_amount() < 2) return S.use(2) @@ -109,7 +116,7 @@ to_chat(user, "You need two sheets of metal to finish a wall!") return to_chat(user, "You start adding plating...") - if (do_after(user, 40, target = src)) + if (do_after(user, 40*platingmodifier, target = src)) if(S.get_amount() < 2) return S.use(2) @@ -126,7 +133,7 @@ to_chat(user, "You need at least two sheets to create a false wall!") return to_chat(user, "You start building a reinforced false wall...") - if(do_after(user, 20, target = src)) + if(do_after(user, 20*platingmodifier, target = src)) if(S.get_amount() < 2) return S.use(2) @@ -139,7 +146,7 @@ if(S.get_amount() < 1) return to_chat(user, "You start finalizing the reinforced wall...") - if(do_after(user, 50, target = src)) + if(do_after(user, 50*platingmodifier, target = src)) if(S.get_amount() < 1) return S.use(1) @@ -153,7 +160,7 @@ if(S.get_amount() < 1) return to_chat(user, "You start reinforcing the girder...") - if(do_after(user, 60, target = src)) + if(do_after(user, 60*platingmodifier, target = src)) if(S.get_amount() < 1) return S.use(1) @@ -172,7 +179,7 @@ if(S.get_amount() < 2) to_chat(user, "You need at least two sheets to create a false wall!") return - if(do_after(user, 20, target = src)) + if(do_after(user, 20*platingmodifier, target = src)) if(S.get_amount() < 2) return S.use(2) @@ -188,7 +195,7 @@ to_chat(user, "You need at least two sheets to add plating!") return to_chat(user, "You start adding plating...") - if (do_after(user, 40, target = src)) + if (do_after(user, 40*platingmodifier, target = src)) if(S.get_amount() < 2) return S.use(2) diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 54e08db210..20151a0bdb 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -267,7 +267,7 @@ var/obj/structure/cable/C = T.get_cable_node() if(C) playsound(src, 'sound/magic/lightningshock.ogg', 100, 1, extrarange = 5) - tesla_zap(src, 3, C.newavail() * 0.01, TESLA_MOB_DAMAGE | TESLA_OBJ_DAMAGE | TESLA_MOB_STUN | TESLA_ALLOW_DUPLICATES) //Zap for 1/100 of the amount of power. At a million watts in the grid, it will be as powerful as a tesla revolver shot. + tesla_zap(src, 3, C.newavail() * 0.01, ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE | ZAP_MOB_STUN | ZAP_ALLOW_DUPLICATES) //Zap for 1/100 of the amount of power. At a million watts in the grid, it will be as powerful as a tesla revolver shot. C.add_delayedload(C.newavail() * 0.0375) // you can gain up to 3.5 via the 4x upgrades power is halved by the pole so thats 2x then 1X then .5X for 3.5x the 3 bounces shock. return ..() diff --git a/code/game/objects/structures/guillotine.dm b/code/game/objects/structures/guillotine.dm index 611a6d024d..0a5ba6a68c 100644 --- a/code/game/objects/structures/guillotine.dm +++ b/code/game/objects/structures/guillotine.dm @@ -130,7 +130,7 @@ // The crowd is pleased // The delay is to making large crowds have a longer laster applause var/delay_offset = 0 - for(var/mob/M in viewers(src, 7)) + for(var/mob/M in fov_viewers(world.view, src)) var/mob/living/carbon/human/C = M if (ishuman(M)) addtimer(CALLBACK(C, /mob/.proc/emote, "clap"), delay_offset * 0.3) diff --git a/code/game/objects/structures/icemoon/cave_entrance.dm b/code/game/objects/structures/icemoon/cave_entrance.dm index 2f3bb23261..e68918c764 100644 --- a/code/game/objects/structures/icemoon/cave_entrance.dm +++ b/code/game/objects/structures/icemoon/cave_entrance.dm @@ -176,3 +176,4 @@ GLOBAL_LIST_INIT(ore_probability, list(/obj/item/stack/ore/uranium = 50, new /obj/item/book/granter/spell/sacredflame(loc) if(28) new /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/doom(loc) + qdel(src) diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index b10ca8002c..38133d9089 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -32,7 +32,6 @@ /obj/structure/janitorialcart/proc/put_in_cart(obj/item/I, mob/user) if(!user.transferItemToLoc(I, src)) return - updateUsrDialog() to_chat(user, "You put [I] into [src].") return @@ -96,70 +95,82 @@ . = ..() if(.) return - user.set_machine(src) - var/dat + + var/list/items = list() if(mybag) - dat += "[mybag.name]
" + items += list("Trash bag" = image(icon = mybag.icon, icon_state = mybag.icon_state)) if(mymop) - dat += "[mymop.name]
" + items += list("Mop" = image(icon = mymop.icon, icon_state = mymop.icon_state)) if(mybroom) - dat += "[mybroom.name]
" + items += list("Broom" = image(icon = mybroom.icon, icon_state = mybroom.icon_state)) if(myspray) - dat += "[myspray.name]
" + items += list("Spray bottle" = image(icon = myspray.icon, icon_state = myspray.icon_state)) if(myreplacer) - dat += "[myreplacer.name]
" - if(signs) - dat += "[signs] sign\s
" - var/datum/browser/popup = new(user, "janicart", name, 240, 160) - popup.set_content(dat) - popup.open() + items += list("Light replacer" = image(icon = myreplacer.icon, icon_state = myreplacer.icon_state)) + var/obj/item/caution/sign = locate() in src + if(sign) + items += list("Sign" = image(icon = sign.icon, icon_state = sign.icon_state)) - -/obj/structure/janitorialcart/Topic(href, href_list) - if(!in_range(src, usr)) + if(!length(items)) return - if(!isliving(usr)) + items = sortList(items) + var/pick = show_radial_menu(user, src, items, custom_check = CALLBACK(src, .proc/check_menu, user), radius = 38, require_near = TRUE) + if(!pick) return - var/mob/living/user = usr - if(href_list["garbage"]) - if(mybag) + switch(pick) + if("Trash bag") + if(!mybag) + return user.put_in_hands(mybag) to_chat(user, "You take [mybag] from [src].") mybag = null - if(href_list["mop"]) - if(mymop) + if("Mop") + if(!mymop) + return user.put_in_hands(mymop) to_chat(user, "You take [mymop] from [src].") mymop = null - if(href_list["broom"]) - if(mybroom) + if("Broom") + if(!mybroom) + return user.put_in_hands(mybroom) to_chat(user, "You take [mybroom] from [src].") mybroom = null - if(href_list["spray"]) - if(myspray) + if("Spray bottle") + if(!myspray) + return user.put_in_hands(myspray) to_chat(user, "You take [myspray] from [src].") myspray = null - if(href_list["replacer"]) - if(myreplacer) + if("Light replacer") + if(!myreplacer) + return user.put_in_hands(myreplacer) to_chat(user, "You take [myreplacer] from [src].") myreplacer = null - if(href_list["sign"]) - if(signs) - var/obj/item/caution/Sign = locate() in src - if(Sign) - user.put_in_hands(Sign) - to_chat(user, "You take \a [Sign] from [src].") - signs-- - else - WARNING("Signs ([signs]) didn't match contents") - signs = 0 + if("Sign") + if(signs <= 0) + return + user.put_in_hands(sign) + to_chat(user, "You take \a [sign] from [src].") + signs-- + else + return update_icon() - updateUsrDialog() +/** + * check_menu: Checks if we are allowed to interact with a radial menu + * + * Arguments: + * * user The mob interacting with a menu + */ +/obj/structure/janitorialcart/proc/check_menu(mob/living/user) + if(!istype(user)) + return FALSE + if(user.incapacitated()) + return FALSE + return TRUE /obj/structure/janitorialcart/update_overlays() . = ..() diff --git a/code/game/objects/structures/ladders.dm b/code/game/objects/structures/ladders.dm index 53a1f609d1..f321498bfd 100644 --- a/code/game/objects/structures/ladders.dm +++ b/code/game/objects/structures/ladders.dm @@ -91,8 +91,13 @@ if (!is_ghost && !in_range(src, user)) return + var/list/tool_list = list( + "Up" = image(icon = 'icons/testing/turf_analysis.dmi', icon_state = "red_arrow", dir = NORTH), + "Down" = image(icon = 'icons/testing/turf_analysis.dmi', icon_state = "red_arrow", dir = SOUTH) + ) + if (up && down) - var/result = alert("Go up or down [src]?", "Ladder", "Up", "Down", "Cancel") + var/result = show_radial_menu(user, src, tool_list, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE, tooltips = TRUE) if (!is_ghost && !in_range(src, user)) return // nice try switch(result) @@ -112,6 +117,11 @@ if(!is_ghost) add_fingerprint(user) +/obj/structure/ladder/proc/check_menu(mob/user) + if(user.incapacitated() || !user.Adjacent(src)) + return FALSE + return TRUE + /obj/structure/ladder/attack_hand(mob/user) . = ..() if(.) diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index c41d6d32af..6e497cff60 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -149,3 +149,30 @@ pixel_x = 0 pixel_y = 0 return TRUE + +/obj/structure/lattice/lava + name = "heatproof support lattice" + desc = "A specialized support beam for building across lava. Watch your step." + icon = 'icons/obj/smooth_structures/catwalk.dmi' + icon_state = "catwalk" + number_of_rods = 1 + color = "#5286b9ff" + smooth = SMOOTH_TRUE + canSmoothWith = null + obj_flags = CAN_BE_HIT | BLOCK_Z_FALL + resistance_flags = FIRE_PROOF | LAVA_PROOF + +/obj/structure/lattice/lava/deconstruction_hints(mob/user) + return "The rods look like they could be cut, but the heat treatment will shatter off. There's space for a tile." + +/obj/structure/lattice/lava/attackby(obj/item/C, mob/user, params) + . = ..() + if(istype(C, /obj/item/stack/tile/plasteel)) + var/obj/item/stack/tile/plasteel/P = C + if(P.use(1)) + to_chat(user, "You construct a floor plating, as lava settles around the rods.") + playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE) + new /turf/open/floor/plating(locate(x, y, z)) + else + to_chat(user, "You need one floor tile to build atop [src].") + return diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index e32def727a..65e1b7dd9a 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -4,6 +4,7 @@ desc = "Mirror mirror on the wall, who's the most robust of them all?" icon = 'icons/obj/watercloset.dmi' icon_state = "mirror" + plane = ABOVE_WALL_PLANE density = FALSE anchored = TRUE max_integrity = 200 diff --git a/code/game/objects/structures/noticeboard.dm b/code/game/objects/structures/noticeboard.dm index f4bca1f900..68da53aa6c 100644 --- a/code/game/objects/structures/noticeboard.dm +++ b/code/game/objects/structures/noticeboard.dm @@ -3,6 +3,7 @@ desc = "A board for pinning important notices upon." icon = 'icons/obj/stationobjs.dmi' icon_state = "nboard00" + plane = ABOVE_WALL_PLANE density = FALSE anchored = TRUE max_integrity = 150 diff --git a/code/game/objects/structures/signs/_signs.dm b/code/game/objects/structures/signs/_signs.dm index 84add2f65f..a1de5fe6a3 100644 --- a/code/game/objects/structures/signs/_signs.dm +++ b/code/game/objects/structures/signs/_signs.dm @@ -3,6 +3,7 @@ anchored = TRUE opacity = 0 density = FALSE + plane = ABOVE_WALL_PLANE layer = SIGN_LAYER max_integrity = 100 armor = list("melee" = 50, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm index 9a6b24b472..1f9491f4cf 100644 --- a/code/game/objects/structures/statues.dm +++ b/code/game/objects/structures/statues.dm @@ -8,12 +8,11 @@ max_integrity = 100 var/oreAmount = 5 var/material_drop_type = /obj/item/stack/sheet/metal + var/impressiveness = 15 CanAtmosPass = ATMOS_PASS_DENSITY - /obj/structure/statue/attackby(obj/item/W, mob/living/user, params) add_fingerprint(user) - user.changeNext_move(CLICK_CD_MELEE) if(!(flags_1 & NODECONSTRUCT_1)) if(default_unfasten_wrench(user, W)) return @@ -36,8 +35,22 @@ return user.changeNext_move(CLICK_CD_MELEE) add_fingerprint(user) - user.visible_message("[user] rubs some dust off from the [name]'s surface.", \ - "You rub some dust off from the [name]'s surface.") + if(!do_after(user, 20, target = src)) + return + user.visible_message("[user] rubs some dust off [src].", \ + "You take in [src], rubbing some dust off its surface.") + if(!ishuman(user)) // only humans have the capacity to appreciate art + return + var/totalimpressiveness = (impressiveness *(obj_integrity/max_integrity)) + switch(totalimpressiveness) + if(GREAT_ART to 100) + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat) + if (GOOD_ART to GREAT_ART) + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artgood", /datum/mood_event/artgood) + if (BAD_ART to GOOD_ART) + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artok", /datum/mood_event/artok) + if (0 to BAD_ART) + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad) /obj/structure/statue/deconstruct(disassembled = TRUE) if(!(flags_1 & NODECONSTRUCT_1)) @@ -58,6 +71,7 @@ material_drop_type = /obj/item/stack/sheet/mineral/uranium var/last_event = 0 var/active = null + impressiveness = 25 // radiation makes an impression /obj/structure/statue/uranium/nuke name = "statue of a nuclear fission explosive" @@ -101,6 +115,7 @@ max_integrity = 200 material_drop_type = /obj/item/stack/sheet/mineral/plasma desc = "This statue is suitably made from plasma." + impressiveness = 20 /obj/structure/statue/plasma/scientist name = "statue of a scientist" @@ -151,6 +166,7 @@ max_integrity = 300 material_drop_type = /obj/item/stack/sheet/mineral/gold desc = "This is a highly valuable statue made from gold." + impressiveness = 30 /obj/structure/statue/gold/hos name = "statue of the head of security" @@ -178,6 +194,7 @@ max_integrity = 300 material_drop_type = /obj/item/stack/sheet/mineral/silver desc = "This is a valuable statue made from silver." + impressiveness = 25 /obj/structure/statue/silver/md name = "statue of a medical officer" @@ -205,6 +222,7 @@ max_integrity = 1000 material_drop_type = /obj/item/stack/sheet/mineral/diamond desc = "This is a very expensive diamond statue." + impressiveness = 60 /obj/structure/statue/diamond/captain name = "statue of THE captain." @@ -225,6 +243,7 @@ material_drop_type = /obj/item/stack/sheet/mineral/bananium desc = "A bananium statue with a small engraving:'HOOOOOOONK'." var/spam_flag = 0 + impressiveness = 65 /obj/structure/statue/bananium/clown name = "statue of a clown" diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 30e451aa14..012d92e103 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -163,6 +163,9 @@ if(istype(I, /obj/item/storage/bag/tray)) var/obj/item/storage/bag/tray/T = I if(T.contents.len > 0) // If the tray isn't empty + for(var/x in T.contents) + var/obj/item/item = x + AfterPutItemOnTable(item, user) SEND_SIGNAL(I, COMSIG_TRY_STORAGE_QUICK_EMPTY, drop_location()) user.visible_message("[user] empties [I] on [src].") return @@ -177,13 +180,17 @@ //Clamp it so that the icon never moves more than 16 pixels in either direction (thus leaving the table turf) I.pixel_x = clamp(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2) I.pixel_y = clamp(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2) - return 1 + AfterPutItemOnTable(I, user) + return TRUE else return ..() +/obj/structure/table/proc/AfterPutItemOnTable(obj/item/I, mob/living/user) + return + /obj/structure/table/alt_attack_hand(mob/user) if(user && Adjacent(user) && !user.incapacitated()) - user.setClickCooldown(4) + user.changeNext_move(CLICK_CD_MELEE*0.5) if(istype(user) && user.a_intent == INTENT_HARM) user.visible_message("[user] slams [user.p_their()] palms down on [src].", "You slam your palms down on [src].") playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 50, 1) @@ -214,6 +221,37 @@ material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS | MATERIAL_EFFECTS buildstack = null //No buildstack, so generate from mat datums +///Table on wheels +/obj/structure/table/rolling + name = "Rolling table" + desc = "A NT brand \"Rolly poly\" rolling table. It can and will move." + anchored = FALSE + smooth = SMOOTH_FALSE + canSmoothWith = list() + icon = 'icons/obj/smooth_structures/rollingtable.dmi' + icon_state = "rollingtable" + var/list/attached_items = list() + +/obj/structure/table/rolling/AfterPutItemOnTable(obj/item/I, mob/living/user) + . = ..() + attached_items += I + RegisterSignal(I, COMSIG_MOVABLE_MOVED, .proc/RemoveItemFromTable) //Listen for the pickup event, unregister on pick-up so we aren't moved + +/obj/structure/table/rolling/proc/RemoveItemFromTable(datum/source, newloc, dir) + if(newloc != loc) //Did we not move with the table? because that shit's ok + return FALSE + attached_items -= source + UnregisterSignal(source, COMSIG_MOVABLE_MOVED) + +/obj/structure/table/rolling/Moved(atom/OldLoc, Dir) + for(var/mob/M in OldLoc.contents)//Kidnap everyone on top + M.forceMove(loc) + for(var/x in attached_items) + var/atom/movable/AM = x + if(!AM.Move(loc)) + RemoveItemFromTable(AM, AM.loc) + return TRUE + /* * Glass tables */ diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm index 17ca178cd9..c3b388fc29 100644 --- a/code/game/objects/structures/transit_tubes/station.dm +++ b/code/game/objects/structures/transit_tubes/station.dm @@ -152,8 +152,8 @@ pod_moving = 0 if(!QDELETED(pod)) var/datum/gas_mixture/floor_mixture = loc.return_air() - ARCHIVE_TEMPERATURE(floor_mixture) - ARCHIVE_TEMPERATURE(pod.air_contents) + ARCHIVE(floor_mixture) + ARCHIVE(pod.air_contents) pod.air_contents.share(floor_mixture, 1) //mix the pod's gas mixture with the tile it's on air_update_turf() diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 95edd15951..fbb1eac7d1 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -520,7 +520,7 @@ if(istype(O, /obj/item/melee/baton)) var/obj/item/melee/baton/B = O if(B.cell) - if(B.cell.charge > 0 && B.status == 1) + if(B.cell.charge > 0 && B.turned_on) flick("baton_active", src) var/stunforce = B.stamforce user.DefaultCombatKnockdown(stunforce * 2) diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm index 04c3909696..4544cab3da 100644 --- a/code/game/objects/structures/windoor_assembly.dm +++ b/code/game/objects/structures/windoor_assembly.dm @@ -169,8 +169,7 @@ if(do_after(user, 40, target = src)) if(!src || !anchored || src.state != "01") return - var/obj/item/stack/cable_coil/CC = W - if(!CC.use(1)) + if(!W.use_tool(src, user, 0, 1)) to_chat(user, "You need more cable to do this!") return to_chat(user, "You wire the windoor.") diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index e4d93ea8de..ba7c0d2fbe 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -1,7 +1,3 @@ -#define NOT_ELECTROCHROMATIC 0 -#define ELECTROCHROMATIC_OFF 1 -#define ELECTROCHROMATIC_DIMMED 2 - GLOBAL_LIST_EMPTY(electrochromatic_window_lookup) /proc/do_electrochromatic_toggle(new_status, id) @@ -74,9 +70,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup) if(reinf && anchored) state = WINDOW_SCREWED_TO_FRAME - if(mapload && electrochromatic_id) - if(copytext(electrochromatic_id, 1, 2) == "!") - electrochromatic_id = SSmapping.get_obfuscated_id(electrochromatic_id) + if(mapload && electrochromatic_id && electrochromatic_id[1] == "!") + electrochromatic_id = SSmapping.get_obfuscated_id(electrochromatic_id) ini_dir = dir air_update_turf(1) @@ -885,7 +880,3 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup) return ..() update_icon() - -#undef NOT_ELECTROCHROMATIC -#undef ELECTROCHROMATIC_OFF -#undef ELECTROCHROMATIC_DIMMED diff --git a/code/game/say.dm b/code/game/say.dm index 5fa5a2b35d..187994f432 100644 --- a/code/game/say.dm +++ b/code/game/say.dm @@ -25,7 +25,7 @@ GLOBAL_LIST_INIT(freqtospan, list( return spans |= speech_span if(!language) - language = get_default_language() + language = get_selected_language() send_speech(message, 7, src, , spans, message_language=language) /atom/movable/proc/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source) diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index 3a719d05b9..38e0839617 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -80,7 +80,10 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( var/old_dynamic_lighting = dynamic_lighting var/old_affecting_lights = affecting_lights var/old_lighting_object = lighting_object - var/old_corners = corners + var/old_lc_topright = lc_topright + var/old_lc_topleft = lc_topleft + var/old_lc_bottomright = lc_bottomright + var/old_lc_bottomleft = lc_bottomleft var/old_exl = explosion_level var/old_exi = explosion_id @@ -119,7 +122,10 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( recalc_atom_opacity() lighting_object = old_lighting_object affecting_lights = old_affecting_lights - corners = old_corners + lc_topright = old_lc_topright + lc_topleft = old_lc_topleft + lc_bottomright = old_lc_bottomright + lc_bottomleft = old_lc_bottomleft if (old_opacity != opacity || dynamic_lighting != old_dynamic_lighting) reconsider_lights() diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm index 99c7ed8231..c7aefbe0a6 100644 --- a/code/game/turfs/closed.dm +++ b/code/game/turfs/closed.dm @@ -1,5 +1,6 @@ /turf/closed layer = CLOSED_TURF_LAYER + plane = WALL_PLANE opacity = 1 density = TRUE blocks_air = 1 diff --git a/code/game/turfs/simulated/floor/plating/asteroid.dm b/code/game/turfs/simulated/floor/plating/asteroid.dm index e4a3c5810c..1fbeee7523 100644 --- a/code/game/turfs/simulated/floor/plating/asteroid.dm +++ b/code/game/turfs/simulated/floor/plating/asteroid.dm @@ -203,8 +203,7 @@ mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/wolf = 50, /obj/structure/spawner/ice_moon = 3, \ /mob/living/simple_animal/hostile/asteroid/polarbear = 30, /obj/structure/spawner/ice_moon/polarbear = 3, \ /mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow = 50, /mob/living/simple_animal/hostile/asteroid/goldgrub = 10) - - flora_spawn_list = list(/obj/structure/flora/tree/pine = 2, /obj/structure/flora/grass/both = 12) + flora_spawn_list = list(/obj/structure/flora/tree/pine = 2, /obj/structure/flora/grass/both = 12, /obj/structure/flora/rock/icy = 6, /obj/structure/flora/rock/pile/icy = 6) data_having_type = /turf/open/floor/plating/asteroid/airless/cave/snow/has_data turf_type = /turf/open/floor/plating/asteroid/snow/icemoon choose_turf_type = list(/turf/open/floor/plating/asteroid/snow/icemoon = 19, /turf/open/floor/plating/ice/icemoon = 1) diff --git a/code/game/turfs/simulated/lava.dm b/code/game/turfs/simulated/lava.dm index dd2b9dfa18..2f223f2c40 100644 --- a/code/game/turfs/simulated/lava.dm +++ b/code/game/turfs/simulated/lava.dm @@ -81,10 +81,25 @@ /turf/open/lava/TakeTemperature(temp) +/turf/open/lava/attackby(obj/item/C, mob/user, params) + ..() + if(istype(C, /obj/item/stack/rods/lava)) + var/obj/item/stack/rods/lava/R = C + var/obj/structure/lattice/lava/H = locate(/obj/structure/lattice/lava, src) + if(H) + to_chat(user, "There is already a lattice here!") + return + if(R.use(1)) + to_chat(user, "You construct a lattice.") + playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE) + new /obj/structure/lattice/lava(locate(x, y, z)) + else + to_chat(user, "You need one rod to build a heatproof lattice.") + return /turf/open/lava/proc/is_safe() //if anything matching this typecache is found in the lava, we don't burn things - var/static/list/lava_safeties_typecache = typecacheof(list(/obj/structure/lattice/catwalk, /obj/structure/stone_tile)) + var/static/list/lava_safeties_typecache = typecacheof(list(/obj/structure/lattice/catwalk, /obj/structure/stone_tile, /obj/structure/lattice/lava)) var/list/found_safeties = typecache_filter_list(contents, lava_safeties_typecache) for(var/obj/structure/stone_tile/S in found_safeties) if(S.fallen) diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 268e8e9109..5243341ac1 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -290,7 +290,7 @@ if(LAZYLEN(dent_decals) >= MAX_DENT_DECALS) return - var/mutable_appearance/decal = mutable_appearance('icons/effects/effects.dmi', "", BULLET_HOLE_LAYER) + var/mutable_appearance/decal = mutable_appearance('icons/effects/effects.dmi', "", BULLET_HOLE_LAYER, ABOVE_WALL_PLANE) switch(denttype) if(WALL_DENT_SHOT) decal.icon_state = "bullet_hole" diff --git a/code/game/world.dm b/code/game/world.dm index 10431e4af9..1c6f3bceba 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -1,6 +1,7 @@ #define RESTART_COUNTER_PATH "data/round_counter.txt" GLOBAL_VAR(restart_counter) +GLOBAL_VAR_INIT(tgs_initialized, FALSE) GLOBAL_VAR(topic_status_lastcache) GLOBAL_LIST(topic_status_cache) @@ -23,10 +24,11 @@ GLOBAL_LIST(topic_status_cache) make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once) - TgsNew(minimum_required_security_level = TGS_SECURITY_TRUSTED) GLOB.revdata = new + InitTgs() + config.Load(params[OVERRIDE_CONFIG_DIRECTORY_PARAMETER]) //SetupLogs depends on the RoundID, so lets check @@ -62,6 +64,15 @@ GLOBAL_LIST(topic_status_cache) if(TEST_RUN_PARAMETER in params) HandleTestRun() +/world/proc/InitTgs() + TgsNew(new /datum/tgs_event_handler/impl, TGS_SECURITY_TRUSTED) + GLOB.revdata.load_tgs_info() +#ifdef USE_CUSTOM_ERROR_HANDLER + if (TgsAvailable()) + world.log = file("[GLOB.log_directory]/dd.log") //not all runtimes trigger world/Error, so this is the only way to ensure we can see all of them. +#endif + GLOB.tgs_initialized = TRUE + /world/proc/HandleTestRun() //trigger things to run the whole process Master.sleep_offline_after_initializations = FALSE @@ -125,6 +136,7 @@ GLOBAL_LIST(topic_status_cache) GLOB.subsystem_log = "[GLOB.log_directory]/subsystem.log" GLOB.reagent_log = "[GLOB.log_directory]/reagents.log" GLOB.world_crafting_log = "[GLOB.log_directory]/crafting.log" + GLOB.click_log = "[GLOB.log_directory]/click.log" #ifdef UNIT_TESTS @@ -144,6 +156,7 @@ GLOBAL_LIST(topic_status_cache) start_log(GLOB.subsystem_log) start_log(GLOB.reagent_log) start_log(GLOB.world_crafting_log) + start_log(GLOB.click_log) GLOB.changelog_hash = md5('html/changelog.html') //for telling if the changelog has changed recently if(fexists(GLOB.config_error_log)) @@ -223,16 +236,17 @@ GLOBAL_LIST(topic_status_cache) qdel(src) //shut it down /world/Reboot(reason = 0, fast_track = FALSE) - TgsReboot() if (reason || fast_track) //special reboot, do none of the normal stuff if (usr) log_admin("[key_name(usr)] Has requested an immediate world restart via client side debugging tools") message_admins("[key_name_admin(usr)] Has requested an immediate world restart via client side debugging tools") - to_chat(world, "Rebooting World immediately due to host request") + to_chat(world, "Rebooting World immediately due to host request.") else to_chat(world, "Rebooting world...") Master.Shutdown() //run SS shutdowns + TgsReboot() + if(TEST_RUN_PARAMETER in params) FinishTestRun() return diff --git a/code/modules/VR/vr_sleeper.dm b/code/modules/VR/vr_sleeper.dm index e79784290b..26ae200990 100644 --- a/code/modules/VR/vr_sleeper.dm +++ b/code/modules/VR/vr_sleeper.dm @@ -22,6 +22,11 @@ sparks.set_up(2,0) sparks.attach(src) update_icon() + new_occupant_dir = dir + +/obj/machinery/vr_sleeper/setDir(newdir) + . = ..() + new_occupant_dir = dir /obj/machinery/vr_sleeper/attackby(obj/item/I, mob/user, params) if(!state_open && !occupant) diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm index 55c55c42de..99bb988be6 100644 --- a/code/modules/admin/admin_investigate.dm +++ b/code/modules/admin/admin_investigate.dm @@ -4,7 +4,7 @@ var/F = file("[GLOB.log_directory]/[subject].html") WRITE_FILE(F, "[TIME_STAMP("hh:mm:ss", FALSE)] [REF(src)] ([x],[y],[z]) || [src] [message]
") -/client/proc/investigate_show(subject in list("notes, memos, watchlist", INVESTIGATE_RCD, INVESTIGATE_RESEARCH, INVESTIGATE_EXONET, INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS, INVESTIGATE_RADIATION, INVESTIGATE_CIRCUIT, INVESTIGATE_NANITES) ) +/client/proc/investigate_show(subject in list("notes, memos, watchlist", INVESTIGATE_RCD, INVESTIGATE_RESEARCH, INVESTIGATE_EXONET, INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS, INVESTIGATE_RADIATION, INVESTIGATE_CIRCUIT, INVESTIGATE_NANITES, INVESTIGATE_CRYOGENICS) ) set name = "Investigate" set category = "Admin" if(!holder) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index e9b8c274a8..289abbe250 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -106,6 +106,7 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list( /client/proc/show_tip, /client/proc/smite, /client/proc/admin_away, + /client/proc/cmd_admin_toggle_fov, /client/proc/roll_dices //CIT CHANGE - Adds dice verb )) GLOBAL_PROTECT(admin_verbs_fun) diff --git a/code/modules/admin/chat_commands.dm b/code/modules/admin/chat_commands.dm index e2ddcdcf6a..9b15729a9e 100644 --- a/code/modules/admin/chat_commands.dm +++ b/code/modules/admin/chat_commands.dm @@ -142,3 +142,51 @@ GLOBAL_LIST(round_end_notifiees) log_admin("[sender.friendly_name] has added [params] to the current round's bunker bypass list.") message_admins("[sender.friendly_name] has added [params] to the current round's bunker bypass list.") return "[params] has been added to the current round's bunker bypass list." + +// More (silly) chat commands citadel added. +/datum/tgs_chat_command/wheelofsalt + name = "wheelofsalt" + help_text = "What are Citadel Station 13 players salting about today? Spin the wheel and find out!" + +/datum/tgs_chat_command/wheelofsalt/Run(datum/tgs_chat_user/sender, params) + var/saltresult = "The wheel of salt [pick("clatters","screams","vibrates","clanks","resonates","groans","moans","squeaks","emits a[pick(" god-forsaken"," lewd"," creepy"," generic","n orgasmic"," demonic")] [pick("airhorn","bike horn","trumpet","clown","latex","vore","dog","laughing")] noise")] as it spins violently... And it seems the salt of the day is the " + var/saltprimarysubject = "[pick("combat","medical","grab","furry","wall","orgasm","cat","ERP","lizard","dog","latex","vision cone","atmospherics","table","chem","vore","dogborg","Skylar Lineman","Mekhi Anderson","Peppermint","rework","cum","dick","cockvore","Medihound","sleeper","belly sleeper","door wires","flightsuit","coder privilege","Developer abuse","ban reason","github self merge","red panda","beret","male catgirl","powergame","hexacrocin","Discord server","Clitadel","Cargonia","Solarian Republic","Main and RP merger","bluespace","salt","chem dispenser theft","Botany","moth","BWOINK","anal vore","stamina","Mason Jakops","mining","noodle","milf","Lavaland","Necropolis","Ashwalker","Chase Redtail","Drew Mint","Pavel Marsk","Joker Amari","Durgit","chaplain","Antag","nanite","Syndicate","Nar-Sie","Ratvar","Cult","maint","Foam-Force","AI","cyborg","ghost","clockwork","cyberpunk","vaporwave","Clown","Leon Beech","Mime","security","research","Megafauna","Bubblegum","Ash Drake","Legion","Colossus","White Shuttle","Changeling","Cowboy","Space Ninja","Poly","Revolutionary","Skyrim","forbidden fruits","xenomorph","blob","Nuclear Operative","crossdressing")]" + var/saltsecondarysubject = "[pick("rework","changes","r34","ban","removal","addition","leak","proposal","fanart","introduction","tabling","ERP","bikeshedding","crossdressing","sprites","semen keg","argument","theft","nerf","screeching","salt","creampie","lewding","murder","kissing","marriage","replacement","fucking","ship","netflix adaptation","dance","remaster","system","voyeur","decoration","pre-order","bukkake","seduction","worship","gangbang","handholding")]" + if(prob(10)) + saltresult += "@here for your salt, all day every day" + if(prob(1)) + saltresult += " @everyone gets some salt this time too" + else + saltresult += "[saltprimarysubject] [saltsecondarysubject]" + return "[saltresult]!" + +/datum/tgs_chat_command/valentine + name = "valentine" + help_text = "Get a random flirt line." + +/datum/tgs_chat_command/valentine/Run(datum/tgs_chat_user/sender, params) + return "[pick(GLOB.flirts)]" + +/datum/tgs_chat_command/despacito + name = "despacito" //someone please high effort this sometime and make it a full on ytdl search + help_text = "This is so sad." + +/datum/tgs_chat_command/despacito/Run() + return "https://www.youtube.com/watch?v=kJQP7kiw5Fk" + +/datum/tgs_chat_command/poly + name = "poly" + help_text = "The Lewder, more applicable Poly speak for Citadel Station 13." + var/list/speech_buffer + +/datum/tgs_chat_command/poly/Run() + LAZYINITLIST(speech_buffer) //I figure this is just safe to do for everything at this point + if(length(speech_buffer)) //Let's not look up the whole json EVERY TIME, just the first time. + return "[pick(speech_buffer)]" + else + var/json_file = file("data/npc_saves/Poly.json") + if(!fexists(json_file)) + return "**BAWWWWWK!** LEAVE THE HEADSET! ***BAWKKKKK!!***" + var/list/json = json_decode(file2text(json_file)) + speech_buffer = json["phrases"] + return "[pick(speech_buffer)]" diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm index c70db70ee8..41662c1cad 100644 --- a/code/modules/admin/secrets.dm +++ b/code/modules/admin/secrets.dm @@ -63,16 +63,12 @@ There can only be one! (40-second delay)
Make all players stupid
Egalitarian Station Mode
+ Anarcho-Capitalist Station Mode
Break all lights
Fix all lights
The floor is lava! (DANGEROUS: extremely lame)
Spawn a custom portal storm

- Flip client movement directions
- Randomize client movement directions
- Set each movement direction manually
- Reset movement directions to default
-
Change bomb cap
Mass Purrbation
Mass Remove Purrbation
@@ -478,6 +474,17 @@ usr.client.ak47s() sound_to_playing_players('sound/misc/ak47s.ogg') + if("ancap") + if(!check_rights(R_FUN)) + return + SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Anarcho-capitalist Station")) + SSeconomy.full_ancap = !SSeconomy.full_ancap + message_admins("[key_name_admin(usr)] toggled Anarcho-capitalist mode") + if(SSeconomy.full_ancap) + priority_announce("The NAP is now in full effect.", null, "commandreport") + else + priority_announce("The NAP has been revoked.", null, "commandreport") + if("guns") if(!check_rights(R_FUN)) return @@ -591,60 +598,6 @@ purrbation.") log_admin("[key_name(usr)] has removed everyone from purrbation.") - if("flipmovement") - if(!check_rights(R_FUN)) - return - if(alert("Flip all movement controls?","Confirm","Yes","Cancel") == "Cancel") - return - var/list/movement_keys = SSinput.movement_keys - for(var/i in 1 to movement_keys.len) - var/key = movement_keys[i] - movement_keys[key] = turn(movement_keys[key], 180) - message_admins("[key_name_admin(usr)] has flipped all movement directions.") - log_admin("[key_name(usr)] has flipped all movement directions.") - - if("randommovement") - if(!check_rights(R_FUN)) - return - if(alert("Randomize all movement controls?","Confirm","Yes","Cancel") == "Cancel") - return - var/list/movement_keys = SSinput.movement_keys - for(var/i in 1 to movement_keys.len) - var/key = movement_keys[i] - movement_keys[key] = turn(movement_keys[key], 45 * rand(1, 8)) - message_admins("[key_name_admin(usr)] has randomized all movement directions.") - log_admin("[key_name(usr)] has randomized all movement directions.") - - if("custommovement") - if(!check_rights(R_FUN)) - return - if(alert("Are you sure you want to change every movement key?","Confirm","Yes","Cancel") == "Cancel") - return - var/list/movement_keys = SSinput.movement_keys - var/list/new_movement = list() - for(var/i in 1 to movement_keys.len) - var/key = movement_keys[i] - - var/msg = "Please input the new movement direction when the user presses [key]. Ex. northeast" - var/title = "New direction for [key]" - var/new_direction = text2dir(input(usr, msg, title) as text|null) - if(!new_direction) - new_direction = movement_keys[key] - - new_movement[key] = new_direction - SSinput.movement_keys = new_movement - message_admins("[key_name_admin(usr)] has configured all movement directions.") - log_admin("[key_name(usr)] has configured all movement directions.") - - if("resetmovement") - if(!check_rights(R_FUN)) - return - if(alert("Are you sure you want to reset movement keys to default?","Confirm","Yes","Cancel") == "Cancel") - return - SSinput.setup_default_movement_keys() - message_admins("[key_name_admin(usr)] has reset all movement keys.") - log_admin("[key_name(usr)] has reset all movement keys.") - if("customportal") if(!check_rights(R_FUN)) return diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm index 26736ddff1..df54df5c7d 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm @@ -1025,8 +1025,6 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null v = SSnpcpool if("SSmobs") v = SSmobs - if("SSmood") - v = SSmood if("SSquirks") v = SSquirks if("SSwet_floors") diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 5530225130..d335cfb171 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -1218,6 +1218,58 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggled Hub Visibility", "[GLOB.hub_visibility ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/client/proc/cmd_admin_toggle_fov() + set category = "Fun" + set name = "Enable/Disable Field of Vision" + + var/static/busy_toggling_fov = FALSE + if(!check_rights(R_ADMIN) || !check_rights(R_FUN)) + return + + var/on_off = CONFIG_GET(flag/use_field_of_vision) + + if(busy_toggling_fov) + to_chat(usr, "A previous call of this function is still busy toggling FoV [on_off ? "on" : "off"]. Have some patiece.") + return + busy_toggling_fov = TRUE + + log_admin("[key_name(usr)] has [on_off ? "disabled" : "enabled"] the Field of Vision configuration.") + CONFIG_SET(flag/use_field_of_vision, !on_off) + + SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggled Field of Vision", "[on_off ? "Enabled" : "Disabled"]")) + + if(on_off) + for(var/k in GLOB.mob_list) + if(!k) + continue + var/mob/M = k + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(!(H.dna?.species.has_field_of_vision)) + continue + else if(!M.has_field_of_vision) + continue + var/datum/component/field_of_vision/FoV = M.GetComponent(/datum/component/field_of_vision) + if(FoV) + qdel(FoV) + CHECK_TICK + else + for(var/k in GLOB.clients) + if(!k) + continue + var/client/C = k + var/mob/M = C.mob + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(!(H.dna?.species.has_field_of_vision)) + continue + else if(!M.has_field_of_vision) + continue + M.LoadComponent(/datum/component/field_of_vision, M.field_of_vision_type) + CHECK_TICK + + busy_toggling_fov = FALSE + /client/proc/smite(mob/living/carbon/human/target as mob) set name = "Smite" set category = "Fun" diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index 4a7abda53c..3184a169fc 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -24,6 +24,8 @@ GLOBAL_LIST_EMPTY(antagonists) var/list/blacklisted_quirks = list(/datum/quirk/nonviolent,/datum/quirk/mute) // Quirks that will be removed upon gaining this antag. Pacifist and mute are default. var/threat = 0 // Amount of threat this antag poses, for dynamic mode + var/list/skill_modifiers + /datum/antagonist/New() GLOB.antagonists += src typecache_datum_blacklist = typecacheof(typecache_datum_blacklist) @@ -68,15 +70,19 @@ GLOBAL_LIST_EMPTY(antagonists) //Proc called when the datum is given to a mind. /datum/antagonist/proc/on_gain() - if(owner && owner.current) - if(!silent) - greet() - apply_innate_effects() - give_antag_moodies() - remove_blacklisted_quirks() - if(is_banned(owner.current) && replace_banned) - replace_banned_player() - SEND_SIGNAL(owner.current, COMSIG_MOB_ANTAG_ON_GAIN, src) + if(!(owner?.current)) + return + if(!silent) + greet() + apply_innate_effects() + give_antag_moodies() + remove_blacklisted_quirks() + if(is_banned(owner.current) && replace_banned) + replace_banned_player() + if(skill_modifiers) + for(var/A in skill_modifiers) + ADD_SINGLETON_SKILL_MODIFIER(owner, A, type) + SEND_SIGNAL(owner.current, COMSIG_MOB_ANTAG_ON_GAIN, src) /datum/antagonist/proc/is_banned(mob/M) if(!M) @@ -99,6 +105,8 @@ GLOBAL_LIST_EMPTY(antagonists) clear_antag_moodies() if(owner) LAZYREMOVE(owner.antag_datums, src) + for(var/A in skill_modifiers) + owner.remove_skill_modifier(GET_SKILL_MOD_ID(A, type)) if(!silent && owner.current) farewell() var/datum/team/team = get_team() diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm index 44116dbe36..9132288415 100644 --- a/code/modules/antagonists/abductor/abductor.dm +++ b/code/modules/antagonists/abductor/abductor.dm @@ -21,6 +21,7 @@ landmark_type = /obj/effect/landmark/abductor/agent greet_text = "Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve." show_in_antagpanel = TRUE + skill_modifiers = list(/datum/skill_modifier/job/level/wiring) /datum/antagonist/abductor/scientist name = "Abductor Scientist" @@ -29,6 +30,7 @@ landmark_type = /obj/effect/landmark/abductor/scientist greet_text = "Use your experimental console and surgical equipment to monitor your agent and experiment upon abducted humans." show_in_antagpanel = TRUE + skill_modifiers = list(/datum/skill_modifier/job/affinity/surgery) /datum/antagonist/abductor/create_team(datum/team/abductor_team/new_team) if(!new_team) diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm index 42e3f71037..b90389094f 100644 --- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm +++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm @@ -492,7 +492,7 @@ user.do_attack_animation(L) - if(L.run_block(src, 0, "[user]'s [src]", ATTACK_TYPE_MELEE, 0, user, check_zone(user.zone_selected)) & BLOCK_SUCCESS) + if(L.mob_run_block(src, 0, "[user]'s [src]", ATTACK_TYPE_MELEE, 0, user, check_zone(user.zone_selected), null) & BLOCK_SUCCESS) playsound(L, 'sound/weapons/genhit.ogg', 50, TRUE) return FALSE diff --git a/code/modules/antagonists/abductor/equipment/glands/electric.dm b/code/modules/antagonists/abductor/equipment/glands/electric.dm index 82ee77d192..7e52f6fcb6 100644 --- a/code/modules/antagonists/abductor/equipment/glands/electric.dm +++ b/code/modules/antagonists/abductor/equipment/glands/electric.dm @@ -23,5 +23,5 @@ addtimer(CALLBACK(src, .proc/zap), rand(30, 100)) /obj/item/organ/heart/gland/electric/proc/zap() - tesla_zap(owner, 4, 8000, TESLA_MOB_DAMAGE | TESLA_OBJ_DAMAGE | TESLA_MOB_STUN) + tesla_zap(owner, 4, 8000, ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE | ZAP_MOB_STUN) playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, TRUE) \ No newline at end of file diff --git a/code/modules/antagonists/abductor/equipment/glands/slime.dm b/code/modules/antagonists/abductor/equipment/glands/slime.dm index 53b8133528..2df4a1fab9 100644 --- a/code/modules/antagonists/abductor/equipment/glands/slime.dm +++ b/code/modules/antagonists/abductor/equipment/glands/slime.dm @@ -10,7 +10,12 @@ /obj/item/organ/heart/gland/slime/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE) ..() owner.faction |= "slime" - owner.grant_language(/datum/language/slime) + owner.grant_language(/datum/language/slime, TRUE, TRUE, LANGUAGE_GLAND) + +/obj/item/organ/heart/gland/slime/Remove(mob/living/carbon/M, special = 0) + ..() + owner.faction -= "slime" + owner.remove_language(/datum/language/slime, TRUE, TRUE, LANGUAGE_GLAND) /obj/item/organ/heart/gland/slime/activate() to_chat(owner, "You feel nauseated!") diff --git a/code/modules/antagonists/abductor/equipment/glands/trauma.dm b/code/modules/antagonists/abductor/equipment/glands/trauma.dm index b6280ec017..103d09d444 100644 --- a/code/modules/antagonists/abductor/equipment/glands/trauma.dm +++ b/code/modules/antagonists/abductor/equipment/glands/trauma.dm @@ -10,9 +10,9 @@ /obj/item/organ/heart/gland/trauma/activate() to_chat(owner, "You feel a spike of pain in your head.") if(prob(33)) - owner.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY)) + owner.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_SURGERY)) else if(prob(20)) - owner.gain_trauma_type(BRAIN_TRAUMA_SEVERE, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY)) + owner.gain_trauma_type(BRAIN_TRAUMA_SEVERE, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_SURGERY)) else - owner.gain_trauma_type(BRAIN_TRAUMA_MILD, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY)) \ No newline at end of file + owner.gain_trauma_type(BRAIN_TRAUMA_MILD, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_SURGERY)) diff --git a/code/modules/antagonists/blob/blob/blob_report.dm b/code/modules/antagonists/blob/blob/blob_report.dm index 4385b732c3..d532121e12 100644 --- a/code/modules/antagonists/blob/blob/blob_report.dm +++ b/code/modules/antagonists/blob/blob/blob_report.dm @@ -8,6 +8,13 @@ var/mach = 0 /datum/station_state/proc/count() + floor = 0 + wall = 0 + r_wall = 0 + window = 0 + door = 0 + grille = 0 + mach = 0 for(var/Z in SSmapping.levels_by_trait(ZTRAIT_STATION)) for(var/turf/T in block(locate(1,1,Z), locate(world.maxx,world.maxy,Z))) // don't count shuttles since they may have just left @@ -48,6 +55,10 @@ else if(ismachinery(O)) mach += 1 + CHECK_TICK + CHECK_TICK + CHECK_TICK + /datum/station_state/proc/score(datum/station_state/result) if(!result) return 0 diff --git a/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm b/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm index fbdeea6b84..91fb538ca3 100644 --- a/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm +++ b/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm @@ -86,7 +86,8 @@ melee_damage_upper = 4 obj_damage = 20 environment_smash = ENVIRONMENT_SMASH_STRUCTURES - attacktext = "hits" + attack_verb_continuous = "hits" + attack_verb_simple = "hit" attack_sound = 'sound/weapons/genhit1.ogg' movement_type = FLYING del_on_death = 1 @@ -205,7 +206,8 @@ melee_damage_lower = 20 melee_damage_upper = 20 obj_damage = 60 - attacktext = "slams" + attack_verb_continuous = "slams" + attack_verb_simple = "slam" attack_sound = 'sound/effects/blobattack.ogg' verb_say = "gurgles" verb_ask = "demands" @@ -284,11 +286,11 @@ if(overmind) //if we have an overmind, we're doing chemical reactions instead of pure damage melee_damage_lower = 4 melee_damage_upper = 4 - attacktext = overmind.blobstrain.blobbernaut_message + attack_verb_continuous = overmind.blobstrain.blobbernaut_message else melee_damage_lower = initial(melee_damage_lower) melee_damage_upper = initial(melee_damage_upper) - attacktext = initial(attacktext) + attack_verb_continuous = initial(attack_verb_continuous) /mob/living/simple_animal/hostile/blob/blobbernaut/death(gibbed) ..(gibbed) diff --git a/code/modules/antagonists/blob/blob/theblob.dm b/code/modules/antagonists/blob/blob/theblob.dm index 5717dc557d..6a73dc579b 100644 --- a/code/modules/antagonists/blob/blob/theblob.dm +++ b/code/modules/antagonists/blob/blob/theblob.dm @@ -207,8 +207,8 @@ if(prob(100 - severity * 30)) new /obj/effect/temp_visual/emp(get_turf(src)) -/obj/structure/blob/tesla_act(power) - ..() +/obj/structure/blob/zap_act(power) + . = ..() if(overmind) if(overmind.blobstrain.tesla_reaction(src, power)) take_damage(power/400, BURN, "energy") diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm b/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm index 98fb69e52c..330116a207 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_integration.dm @@ -113,3 +113,5 @@ /mob/living/proc/StartFrenzy(inTime = 120) set waitfor = FALSE + + diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm index 1867be1594..4e4b270c12 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm @@ -177,7 +177,7 @@ if(owner.current.blood_volume < BLOOD_VOLUME_BAD / 2) owner.current.blur_eyes(8 - 8 * (owner.current.blood_volume / BLOOD_VOLUME_BAD)) // Nutrition - owner.current.nutrition = clamp(owner.current.blood_volume, 545, 0) //The amount of blood is how full we are. + owner.current.set_nutrition(min(owner.current.blood_volume, NUTRITION_LEVEL_FULL)) //The amount of blood is how full we are. //A bit higher regeneration based on blood volume if(owner.current.blood_volume < 700) additional_regen = 0.4 @@ -216,8 +216,8 @@ // for (var/datum/action/bloodsucker/masquerade/P in powers) // P.Deactivate() // TEMP DEATH - var/total_brute = owner.current.getBruteLoss() - var/total_burn = owner.current.getFireLoss() + var/total_brute = owner.current.getBruteLoss_nonProsthetic() + var/total_burn = owner.current.getFireLoss_nonProsthetic() var/total_toxloss = owner.current.getToxLoss() //This is neater than just putting it in total_damage var/total_damage = total_brute + total_burn + total_toxloss // Died? Convert to Torpor (fake death) @@ -331,7 +331,7 @@ return var/mob/living/carbon/C = owner.current // Remove Nutrition, Give Bad Food - C.nutrition -= food_nutrition + C.adjust_nutrition(-food_nutrition) foodInGut += food_nutrition // Already ate some bad clams? Then we can back out, because we're already sick from it. if(foodInGut != food_nutrition) diff --git a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm index 2e9d3c1788..888db8193b 100644 --- a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm +++ b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm @@ -20,7 +20,7 @@ var/poweron_feed = FALSE // Am I feeding? var/poweron_masquerade = FALSE // STATS - var/bloodsucker_level + var/bloodsucker_level var/bloodsucker_level_unspent = 1 var/regen_rate = 0.3 // How fast do I regenerate? var/additional_regen // How much additional blood regen we gain from bonuses such as high blood. @@ -39,7 +39,7 @@ var/passive_blood_drain = -0.1 //The amount of blood we loose each bloodsucker life() tick // LISTS var/static/list/defaultTraits = list (TRAIT_STABLEHEART, TRAIT_NOBREATH, TRAIT_SLEEPIMMUNE, TRAIT_NOCRITDAMAGE, TRAIT_RESISTCOLD, TRAIT_RADIMMUNE, TRAIT_NIGHT_VISION, \ - TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_AGEUSIA, TRAIT_COLDBLOODED, TRAIT_NONATURALHEAL, TRAIT_NOMARROW, TRAIT_NOPULSE, TRAIT_VIRUSIMMUNE) + TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_AGEUSIA, TRAIT_COLDBLOODED, TRAIT_NONATURALHEAL, TRAIT_NOMARROW, TRAIT_NOPULSE, TRAIT_VIRUSIMMUNE, TRAIT_NODECAP, TRAIT_NOGUT) /datum/antagonist/bloodsucker/on_gain() SSticker.mode.bloodsuckers |= owner // Add if not already in here (and you might be, if you were picked at round start) @@ -209,7 +209,7 @@ // Physiology CheckVampOrgans() // Heart, Eyes // Language - owner.current.grant_language(/datum/language/vampiric) + owner.current.grant_language(/datum/language/vampiric, TRUE, TRUE, LANGUAGE_BLOODSUCKER) owner.hasSoul = FALSE // If false, renders the character unable to sell their soul. owner.isholy = FALSE // is this person a chaplain or admin role allowed to use bibles // Disabilities @@ -246,7 +246,7 @@ // Update Health owner.current.setMaxHealth(100) // Language - owner.current.remove_language(/datum/language/vampiric) + owner.current.remove_language(/datum/language/vampiric, TRUE, TRUE, LANGUAGE_BLOODSUCKER) // Soul if (owner.soulOwner == owner) // Return soul, if *I* own it. owner.hasSoul = TRUE @@ -649,10 +649,10 @@ return TRUE // Check 3) If I am a BLOODSUCKER, then are they my Vassal? if (mob_B && atom_V && (atom_V in mob_B.vassals)) - return TRUE + return TRUE // Check 4) If we are both VASSAL, then do we have the same master? if (atom_V && mob_V && atom_V.master == mob_V.master) - return TRUE + return TRUE return FALSE @@ -710,7 +710,7 @@ invisibility = INVISIBILITY_ABSTRACT /obj/screen/bloodsucker/proc/update_counter(value, valuecolor) - invisibility = 0 + invisibility = 0 /obj/screen/bloodsucker/blood_counter icon = 'icons/mob/actions/bloodsucker.dmi' @@ -758,7 +758,7 @@ /obj/screen/bloodsucker/sunlight_counter/update_counter(value, valuecolor) ..() - maptext = "
[value]
" + maptext = "
[value]
" /datum/antagonist/bloodsucker/proc/count_vassals(datum/mind/master) var/datum/antagonist/bloodsucker/B = master.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) diff --git a/code/modules/antagonists/bloodsucker/datum_vassal.dm b/code/modules/antagonists/bloodsucker/datum_vassal.dm index 3d5ed1369b..c065d5fe7c 100644 --- a/code/modules/antagonists/bloodsucker/datum_vassal.dm +++ b/code/modules/antagonists/bloodsucker/datum_vassal.dm @@ -48,7 +48,7 @@ objectives += vassal_objective objectives_given += vassal_objective give_thrall_eyes() - owner.current.grant_language(/datum/language/vampiric) + owner.current.grant_language(/datum/language/vampiric, TRUE, TRUE, LANGUAGE_VASSAL) // Add Antag HUD update_vassal_icons_added(owner.current, "vassal") . = ..() @@ -81,7 +81,7 @@ qdel(O) objectives_given = list() remove_thrall_eyes() - owner.current.remove_language(/datum/language/vampiric) + owner.current.remove_language(/datum/language/vampiric, TRUE, TRUE, LANGUAGE_VASSAL) // Clear Antag HUD update_vassal_icons_removed(owner.current) diff --git a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm index 7998a33c7b..090ef45d89 100644 --- a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm +++ b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm @@ -328,8 +328,8 @@ // to_chat(user, "The ritual has been interrupted!") // useLock = FALSE // return - user.playsound_local(null, 'sound/effects/explosion_distant.ogg', 40, TRUE) - target.playsound_local(null, 'sound/effects/explosion_distant.ogg', 40, TRUE) + user.playsound_local(null, 'sound/effects/explosion_distant.ogg', 40, TRUE) + target.playsound_local(null, 'sound/effects/explosion_distant.ogg', 40, TRUE) target.playsound_local(null, 'sound/effects/singlebeat.ogg', 40, TRUE) target.Jitter(25) target.emote("laugh") @@ -490,13 +490,14 @@ update_icon() /obj/structure/bloodsucker/candelabrum/process() - if(lit) - for(var/mob/living/carbon/human/H in viewers(7, src)) - var/datum/antagonist/vassal/T = H.mind.has_antag_datum(ANTAG_DATUM_VASSAL) - if(AmBloodsucker(H) || T) //We dont want vassals or vampires affected by this - return - H.hallucination = 20 - SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "vampcandle", /datum/mood_event/vampcandle) + if(!lit) + return + for(var/mob/living/carbon/human/H in fov_viewers(7, src)) + var/datum/antagonist/vassal/T = H.mind.has_antag_datum(ANTAG_DATUM_VASSAL) + if(AmBloodsucker(H) || T) //We dont want vassals or vampires affected by this + return + H.hallucination = 20 + SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "vampcandle", /datum/mood_event/vampcandle) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // OTHER THINGS TO USE: HUMAN BLOOD. /obj/effect/decal/cleanable/blood diff --git a/code/modules/antagonists/bloodsucker/powers/cloak.dm b/code/modules/antagonists/bloodsucker/powers/cloak.dm index 347700ca9a..5383e8c1ac 100644 --- a/code/modules/antagonists/bloodsucker/powers/cloak.dm +++ b/code/modules/antagonists/bloodsucker/powers/cloak.dm @@ -19,10 +19,9 @@ if(!.) return // must have nobody around to see the cloak - for(var/mob/living/M in viewers(9, owner)) - if(M != owner) - to_chat(owner, "You may only vanish into the shadows unseen.") - return FALSE + for(var/mob/living/M in fov_viewers(9, owner) - owner) + to_chat(owner, "You may only vanish into the shadows unseen.") + return FALSE return TRUE /datum/action/bloodsucker/cloak/ActivatePower() @@ -35,7 +34,7 @@ // Pay Blood Toll (if awake) owner.alpha = max(35, owner.alpha - min(75, 10 + 5 * level_current)) bloodsuckerdatum.AddBloodVolume(-0.2) - + runintent = (user.m_intent == MOVE_INTENT_RUN) var/turf/T = get_turf(user) lum = T.get_lumcount() @@ -50,7 +49,7 @@ if(!runintent) user.toggle_move_intent() REMOVE_TRAIT(user, TRAIT_NORUNNING, "cloak of darkness") - + sleep(5) // Check every few ticks /datum/action/bloodsucker/cloak/ContinueActive(mob/living/user, mob/living/target) diff --git a/code/modules/antagonists/bloodsucker/powers/feed.dm b/code/modules/antagonists/bloodsucker/powers/feed.dm index 8ac4fcebc1..a113f9c083 100644 --- a/code/modules/antagonists/bloodsucker/powers/feed.dm +++ b/code/modules/antagonists/bloodsucker/powers/feed.dm @@ -43,10 +43,14 @@ to_chat(owner, "Lesser beings require a tighter grip.") return FALSE // Bloodsuckers: - else if(iscarbon(target) && target.mind && target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)) - if(display_error) - to_chat(owner, "Other Bloodsuckers will not fall for your subtle approach.") - return FALSE + else if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(!H.can_inject(owner, TRUE, BODY_ZONE_CHEST)) + return FALSE + if(target.mind && target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)) + if(display_error) + to_chat(owner, "Other Bloodsuckers will not fall for your subtle approach.") + return FALSE // Must have Target if(!target) // || !ismob(target) if(display_error) @@ -63,6 +67,8 @@ return FALSE if(ishuman(target)) var/mob/living/carbon/human/H = target + if(!H.can_inject(owner, TRUE, BODY_ZONE_HEAD) && target == owner.pulling && owner.grab_state < GRAB_AGGRESSIVE) + return FALSE if(NOBLOOD in H.dna.species.species_traits)// || owner.get_blood_id() != target.get_blood_id()) if(display_error) to_chat(owner, "Your victim's blood is not suitable for you to take.") @@ -169,8 +175,8 @@ vision_distance = notice_range, ignored_mobs = target) // Only people who AREN'T the target will notice this action. // Warn Feeder about Witnesses... var/was_unnoticed = TRUE - for(var/mob/living/M in viewers(notice_range, owner)) - if(M != owner && M != target && iscarbon(M) && M.mind && !M.silicon_privileges && !M.eye_blind && !M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)) + for(var/mob/living/M in fov_viewers(notice_range, owner) - owner - target) + if(M.client && !M.silicon_privileges && !M.eye_blind && !M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)) was_unnoticed = FALSE break if(was_unnoticed) diff --git a/code/modules/antagonists/bloodsucker/powers/go_home.dm b/code/modules/antagonists/bloodsucker/powers/go_home.dm index 4788d7639e..c46a7fce6c 100644 --- a/code/modules/antagonists/bloodsucker/powers/go_home.dm +++ b/code/modules/antagonists/bloodsucker/powers/go_home.dm @@ -64,8 +64,8 @@ var/turf/T = get_turf(user) if(T && T.lighting_object && T.get_lumcount()>= 0.1) // B) Check for Viewers - for(var/mob/living/M in viewers(get_turf(owner))) - if(M != owner && isliving(M) && M.mind && !M.silicon_privileges && !M.eye_blind) // M.client <--- add this in after testing! + for(var/mob/living/M in fov_viewers(world.view, get_turf(owner)) - owner) + if(M.client && !M.silicon_privileges && !M.eye_blind) am_seen = TRUE if (!M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)) drop_item = TRUE diff --git a/code/modules/antagonists/bloodsucker/powers/mesmerize.dm b/code/modules/antagonists/bloodsucker/powers/mesmerize.dm index 814ad2abd7..eea80d52f3 100644 --- a/code/modules/antagonists/bloodsucker/powers/mesmerize.dm +++ b/code/modules/antagonists/bloodsucker/powers/mesmerize.dm @@ -64,7 +64,7 @@ to_chat(owner, "Your victim's eyes are glazed over. They cannot perceive you.") return FALSE // Check: Target See Me? (behind wall) - if(!(target in viewers(target_range, get_turf(owner)))) + if(!(owner in target.fov_view())) // Sub-Check: GET CLOSER //if (!(owner in range(target_range, get_turf(target))) // if (display_error) @@ -117,8 +117,6 @@ RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/ContinueTarget) // 5 second windup addtimer(CALLBACK(src, .proc/apply_effects, L, target, power_time), 6 SECONDS) - ADD_TRAIT(target, TRAIT_COMBAT_MODE_LOCKED, src) - ADD_TRAIT(L, TRAIT_COMBAT_MODE_LOCKED, src) /datum/action/bloodsucker/targeted/mesmerize/proc/apply_effects(aggressor, victim, power_time) var/mob/living/carbon/target = victim @@ -127,7 +125,6 @@ return PowerActivatedSuccessfully() // blood & cooldown only altered if power activated successfully - less "fuck you"-y target.apply_status_effect(STATUS_EFFECT_MESMERIZE, power_time) - REMOVE_TRAIT(L, TRAIT_COMBAT_MODE_LOCKED, src) target.face_atom(L) target.Stun(power_time) to_chat(L, "[target] is fixed in place by your hypnotic gaze.") @@ -136,8 +133,7 @@ spawn(power_time) if(istype(target) && success) target.notransform = FALSE - REMOVE_TRAIT(target, TRAIT_COMBAT_MODE_LOCKED, src) - if(istype(L) && target.stat == CONSCIOUS && (target in view(10, get_turf(L)))) // They Woke Up! (Notice if within view) + if(istype(L) && target.stat == CONSCIOUS && (target in L.fov_view(10))) // They Woke Up! (Notice if within view) to_chat(L, "[target] has snapped out of their trance.") diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index 9dbcaf7ec2..106ae16031 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -78,6 +78,7 @@ create_initial_profile() if(give_objectives) forge_objectives() + owner.current.grant_all_languages(FALSE, FALSE, TRUE) //Grants omnitongue. We are able to transform our body after all. remove_clownmut() . = ..() diff --git a/code/modules/antagonists/changeling/powers/absorb.dm b/code/modules/antagonists/changeling/powers/absorb.dm index c3c4ec78a3..3e2ff6f3dd 100644 --- a/code/modules/antagonists/changeling/powers/absorb.dm +++ b/code/modules/antagonists/changeling/powers/absorb.dm @@ -59,12 +59,12 @@ changeling.trueabsorbs++ if(user.nutrition < NUTRITION_LEVEL_WELL_FED) - user.nutrition = min((user.nutrition + target.nutrition), NUTRITION_LEVEL_WELL_FED) + user.adjust_nutrition(target.nutrition, NUTRITION_LEVEL_WELL_FED) - if(target.mind)//if the victim has got a mind - // Absorb a lizard, speak Draconic. - user.copy_known_languages_from(target) + // Absorb a lizard, speak Draconic. + user.copy_languages(target, LANGUAGE_ABSORB) + if(target.mind && user.mind)//if the victim and user have minds target.mind.show_memory(user, 0) //I can read your mind, kekeke. Output all their notes. //Some of target's recent speech, so the changeling can attempt to imitate them better. diff --git a/code/modules/antagonists/changeling/powers/adrenaline.dm b/code/modules/antagonists/changeling/powers/adrenaline.dm index ba40388844..32171a036a 100644 --- a/code/modules/antagonists/changeling/powers/adrenaline.dm +++ b/code/modules/antagonists/changeling/powers/adrenaline.dm @@ -13,5 +13,5 @@ //Recover from stuns. /obj/effect/proc_holder/changeling/adrenaline/sting_action(mob/living/user) - user.do_adrenaline(0, FALSE, 70, 0, TRUE, list(/datum/reagent/medicine/epinephrine = 3, /datum/reagent/drug/methamphetamine/changeling = 10, /datum/reagent/medicine/mannitol = 10, /datum/reagent/medicine/regen_jelly = 10, /datum/reagent/medicine/changelingadrenaline = 5), "Energy rushes through us.", 0, 0.75, 0) - return TRUE \ No newline at end of file + user.do_adrenaline(0, FALSE, 70, 0, TRUE, list(/datum/reagent/medicine/epinephrine = 3, /datum/reagent/drug/methamphetamine/changeling = 10, /datum/reagent/medicine/changelingadrenaline = 5), "Energy rushes through us.", 0, 0.75, 0) + return TRUE diff --git a/code/modules/antagonists/changeling/powers/augmented_eyesight.dm b/code/modules/antagonists/changeling/powers/augmented_eyesight.dm index 6eafeda63f..a6fdf7008a 100644 --- a/code/modules/antagonists/changeling/powers/augmented_eyesight.dm +++ b/code/modules/antagonists/changeling/powers/augmented_eyesight.dm @@ -27,12 +27,12 @@ var/obj/item/organ/eyes/E = user.getorganslot(ORGAN_SLOT_EYES) if(E) if(!active) - E.sight_flags |= SEE_MOBS | SEE_OBJS | SEE_TURFS //Add sight flags to the user's eyes + ADD_TRAIT(user, TRAIT_THERMAL_VISION, CHANGELING_TRAIT) E.flash_protect = -1 //Adjust the user's eyes' flash protection to_chat(user, "We adjust our eyes to sense prey through walls.") active = TRUE //Defined in code/modules/spells/spell.dm else - E.sight_flags ^= SEE_MOBS | SEE_OBJS | SEE_TURFS //Remove sight flags from the user's eyes + REMOVE_TRAIT(user, TRAIT_THERMAL_VISION, CHANGELING_TRAIT) E.flash_protect = 2 //Adjust the user's eyes' flash protection to_chat(user, "We adjust our eyes to protect them from bright lights.") active = FALSE @@ -47,10 +47,8 @@ /obj/effect/proc_holder/changeling/augmented_eyesight/on_refund(mob/user) //Get rid of X-ray vision and flash protection when the user refunds this ability action.Remove(user) + REMOVE_TRAIT(user, TRAIT_THERMAL_VISION, CHANGELING_TRAIT) var/obj/item/organ/eyes/E = user.getorganslot(ORGAN_SLOT_EYES) if(E) - if (active) - E.sight_flags ^= SEE_MOBS | SEE_OBJS | SEE_TURFS - else - E.flash_protect = 0 - user.update_sight() \ No newline at end of file + E.flash_protect = initial(E.flash_protect) + user.update_sight() diff --git a/code/modules/antagonists/changeling/powers/biodegrade.dm b/code/modules/antagonists/changeling/powers/biodegrade.dm index f58b90d8e6..db4e47aa78 100644 --- a/code/modules/antagonists/changeling/powers/biodegrade.dm +++ b/code/modules/antagonists/changeling/powers/biodegrade.dm @@ -2,7 +2,7 @@ name = "Biodegrade" desc = "Dissolves restraints or other objects preventing free movement." helptext = "This is obvious to nearby people, and can destroy standard restraints and closets. This ability is somewhat loud, and carries a small risk of our blood gaining violent sensitivity to heat." - chemical_cost = 30 //High cost to prevent spam + chemical_cost = 15 //High cost to prevent spam loudness = 1 dna_cost = 2 req_human = 1 diff --git a/code/modules/antagonists/changeling/powers/chameleon_skin.dm b/code/modules/antagonists/changeling/powers/chameleon_skin.dm index 03f3aab473..c01a1e40c8 100644 --- a/code/modules/antagonists/changeling/powers/chameleon_skin.dm +++ b/code/modules/antagonists/changeling/powers/chameleon_skin.dm @@ -3,7 +3,6 @@ desc = "Our skin pigmentation rapidly changes to suit our current environment." helptext = "Allows us to become invisible after a few seconds of standing still. Can be toggled on and off." dna_cost = 2 - chemical_cost = 25 req_human = 1 action_icon = 'icons/mob/actions/actions_changeling.dmi' action_icon_state = "ling_camouflage" @@ -23,4 +22,4 @@ action.Remove(user) if(user.has_dna()) var/mob/living/carbon/C = user - C.dna.remove_mutation(CHAMELEON) \ No newline at end of file + C.dna.remove_mutation(CHAMELEON) diff --git a/code/modules/antagonists/changeling/powers/fleshmend.dm b/code/modules/antagonists/changeling/powers/fleshmend.dm index 9672d79ee4..afef2a10c7 100644 --- a/code/modules/antagonists/changeling/powers/fleshmend.dm +++ b/code/modules/antagonists/changeling/powers/fleshmend.dm @@ -1,8 +1,9 @@ /obj/effect/proc_holder/changeling/fleshmend name = "Fleshmend" - desc = "Our flesh rapidly regenerates, healing our burns, bruises, and shortness of breath. Functions while unconscious." + desc = "Our flesh rapidly regenerates, healing our burns, bruises, and shortness of breath. Functions while unconscious. This ability is loud, and might cause our blood to react violently to heat." helptext = "If we are on fire, the healing effect will not function. Does not regrow limbs or restore lost blood." chemical_cost = 20 + loudness = 2 dna_cost = 2 req_stat = UNCONSCIOUS action_icon = 'icons/mob/actions/actions_changeling.dmi' diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index aefeb43db9..5378ea2276 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -137,7 +137,7 @@ name = "Arm Blade" desc = "We reform one of our arms into a deadly blade." helptext = "We may retract our armblade in the same manner as we form it. Cannot be used while in lesser form. This ability is loud, and might cause our blood to react violently to heat." - chemical_cost = 20 + chemical_cost = 10 dna_cost = 2 loudness = 2 req_human = 1 @@ -410,7 +410,7 @@ desc = "We reform one of our arms into a hard shield." helptext = "Organic tissue cannot resist damage forever; the shield will break after it is hit too much. The more genomes we absorb, the stronger it is. Cannot be used while in lesser form. This ability is somewhat loud, and carries a small risk of our blood gaining violent sensitivity to heat." chemical_cost = 20 - dna_cost = 1 + dna_cost = 2 loudness = 1 req_human = 1 action_icon = 'icons/mob/actions/actions_changeling.dmi' @@ -522,12 +522,12 @@ /obj/effect/proc_holder/changeling/suit/armor name = "Chitinous Armor" desc = "We turn our skin into tough chitin to protect us from damage." - helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Cannot be used in lesser form. This ability is loud, and might cause our blood to react violently to heat." + helptext = "Upkeep of the armor requires a constant expenditure of chemicals, resulting in a reduced chemical generation. The armor is strong against brute force, but does not provide much protection from lasers. Cannot be used in lesser form. This ability is loud, and might cause our blood to react violently to heat." chemical_cost = 20 dna_cost = 1 loudness = 2 req_human = 1 - recharge_slowdown = 0.25 + recharge_slowdown = 0.5 action_icon = 'icons/mob/actions/actions_changeling.dmi' action_icon_state = "ling_armor" action_background_icon_state = "bg_ling" @@ -543,7 +543,7 @@ icon_state = "lingarmor" item_flags = DROPDEL body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 20, "bomb" = 10, "bio" = 4, "rad" = 0, "fire" = 90, "acid" = 90) + armor = list("melee" = 70, "bullet" = 60, "laser" = 30, "energy" = 40, "bomb" = 10, "bio" = 4, "rad" = 0, "fire" = 50, "acid" = 90) flags_inv = HIDEJUMPSUIT cold_protection = 0 heat_protection = 0 @@ -559,7 +559,7 @@ desc = "A tough, hard covering of black chitin with transparent chitin in front." icon_state = "lingarmorhelmet" item_flags = DROPDEL - armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 20, "bomb" = 10, "bio" = 4, "rad" = 0, "fire" = 90, "acid" = 90) + armor = list("melee" = 70, "bullet" = 60, "laser" = 30, "energy" = 40, "bomb" = 10, "bio" = 4, "rad" = 0, "fire" = 50, "acid" = 90) flags_inv = HIDEEARS|HIDEHAIR|HIDEEYES|HIDEFACIALHAIR|HIDEFACE /obj/item/clothing/head/helmet/changeling/Initialize() diff --git a/code/modules/antagonists/changeling/powers/shriek.dm b/code/modules/antagonists/changeling/powers/shriek.dm index 3de220dbcb..cfea9fcf1e 100644 --- a/code/modules/antagonists/changeling/powers/shriek.dm +++ b/code/modules/antagonists/changeling/powers/shriek.dm @@ -3,7 +3,7 @@ desc = "Our lungs and vocal cords shift, allowing us to briefly emit a noise that deafens and confuses the weak-minded." helptext = "Emits a high-frequency sound that confuses and deafens humans, blows out nearby lights and overloads cyborg sensors. This ability is somewhat loud, and carries a small risk of our blood gaining violent sensitivity to heat." chemical_cost = 20 - dna_cost = 1 + dna_cost = 2 loudness = 1 req_human = 1 action_icon = 'icons/mob/actions/actions_changeling.dmi' @@ -37,7 +37,7 @@ desc = "We shift our vocal cords to release a high-frequency sound that overloads nearby electronics." helptext = "Emits a high-frequency sound that overloads nearby electronics. This ability is somewhat loud, and carries a small risk of our blood gaining violent sensitivity to heat." chemical_cost = 20 - dna_cost = 1 + dna_cost = 2 loudness = 1 action_icon = 'icons/mob/actions/actions_changeling.dmi' action_icon_state = "ling_dissonant" diff --git a/code/modules/antagonists/changeling/powers/strained_muscles.dm b/code/modules/antagonists/changeling/powers/strained_muscles.dm index d8572f04cc..68451012f6 100644 --- a/code/modules/antagonists/changeling/powers/strained_muscles.dm +++ b/code/modules/antagonists/changeling/powers/strained_muscles.dm @@ -5,7 +5,6 @@ name = "Strained Muscles" desc = "We evolve the ability to reduce the acid buildup in our muscles, allowing us to move much faster." helptext = "The strain will make us tired, and we will rapidly become fatigued. Standard weight restrictions, like hardsuits, still apply. Cannot be used in lesser form." - chemical_cost = 15 dna_cost = 1 req_human = 1 var/stacks = 0 //Increments every 5 seconds; damage increases over time @@ -15,16 +14,13 @@ action_background_icon_state = "bg_ling" /obj/effect/proc_holder/changeling/strained_muscles/sting_action(mob/living/carbon/user) - var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling) active = !active if(active) to_chat(user, "Our muscles tense and strengthen.") - changeling.chem_recharge_slowdown += 0.5 else user.remove_movespeed_modifier(/datum/movespeed_modifier/strained_muscles) to_chat(user, "Our muscles relax.") - changeling.chem_recharge_slowdown -= 0.5 - if(stacks >= 20) + if(stacks >= 10) to_chat(user, "We collapse in exhaustion.") user.DefaultCombatKnockdown(60) user.emote("gasp") @@ -34,7 +30,6 @@ return TRUE /obj/effect/proc_holder/changeling/strained_muscles/proc/muscle_loop(mob/living/carbon/user) - var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling) while(active) user.add_movespeed_modifier(/datum/movespeed_modifier/strained_muscles) if(user.stat != CONSCIOUS || user.staminaloss >= 90) @@ -42,18 +37,17 @@ to_chat(user, "Our muscles relax without the energy to strengthen them.") user.DefaultCombatKnockdown(40) user.remove_movespeed_modifier(/datum/movespeed_modifier/strained_muscles) - changeling.chem_recharge_slowdown -= 0.5 break stacks++ //user.take_bodypart_damage(stacks * 0.03, 0) - user.adjustStaminaLoss(stacks*1.3) //At first the changeling may regenerate stamina fast enough to nullify fatigue, but it will stack + user.adjustStaminaLoss(stacks*1.5) //At first the changeling may regenerate stamina fast enough to nullify fatigue, but it will stack - if(stacks == 10) //Warning message that the stacks are getting too high + if(stacks == 5) //Warning message that the stacks are getting too high to_chat(user, "Our legs are really starting to hurt...") sleep(40) - while(!active && stacks) //Damage stacks decrease fairly rapidly while not in sanic mode + while(!active && stacks) //Damage stacks decrease slowly while not in sanic mode stacks-- - sleep(20) + sleep(100) diff --git a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm index 431416ede0..036ea37ada 100644 --- a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm +++ b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm @@ -5,6 +5,7 @@ clockwork_desc = "A sigil of some purpose." icon_state = "sigil" layer = LOW_OBJ_LAYER + plane = ABOVE_WALL_PLANE alpha = 50 resistance_flags = NONE var/affects_servants = FALSE diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_shield.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_shield.dm new file mode 100644 index 0000000000..a681e9b38b --- /dev/null +++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_shield.dm @@ -0,0 +1,82 @@ +//Subtype of (riot) shield because of already implemented shieldbash stuff aswell as integrity and simillar things +//ratvarian shield: A shield that absorbs energy from attacks and uses it to empower its bashes with remendous force. It is also quite resistant to damage, though less so against lasers and energy weaponry. + +/obj/item/shield/riot/ratvarian + name = "ratvarian shield" + icon_state = "ratvarian_shield" //Its icons are in the same place the normal shields are in + item_state = "ratvarian_shield" + desc = "A resilient shield made out of brass.. It feels warm to the touch." + var/clockwork_desc = "A powerful shield of ratvarian making. It absorbs blocked attacks to charge devastating bashes." + armor = list("melee" = 80, "bullet" = 70, "laser" = -10, "energy" = -20, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100) + shield_flags = SHIELD_FLAGS_DEFAULT + max_integrity = 300 //High integrity, extremely strong against melee / bullets, but still quite easy to destroy with lasers and energy + repair_material = /obj/item/stack/tile/brass + var/dam_absorbed = 0 + var/bash_mult_steps = 30 + var/max_bash_mult = 4 + +/obj/item/shield/riot/ratvarian/examine(mob/user) + if((is_servant_of_ratvar(user) || isobserver(user))) + desc = clockwork_desc + desc +="\n The shield has absorbed [dam_absorbed] damage, multiplying the effectiveness of its bashes by [calc_bash_mult()]" + . = ..() + desc = initial(desc) + +obj/item/shield/riot/ratvarian/proc/calc_bash_mult() + var/bash_mult = 0 + if(!dam_absorbed) + return 1 + else + bash_mult += round(clamp(1 + (dam_absorbed / bash_mult_steps), 1, max_bash_mult), 0.1) //Multiplies the effect of bashes by up to [max_bash_mult], though never less than one + return bash_mult + +/obj/item/shield/riot/ratvarian/proc/calc_bash_absorb_use() + var/absorb_use = 0 + absorb_use = max(0, round(dam_absorbed * (calc_bash_mult() / round(1 + (dam_absorbed / bash_mult_steps), 0.1)), 1)) //Calculates how much of the absorbed damage the bash would actually use, so its not wasted + return absorb_use + +/obj/item/shield/riot/ratvarian/on_shield_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(!damage) + return ..() + + if(!is_servant_of_ratvar(owner)) + owner.visible_message("As [owner] blocks the attack with [src], [owner.p_they()] suddenly drops it, whincing in pain! ", "As you block the attack with [src], it heats up tremendously, forcing you to drop it from the pain alone! ") + owner.emote("scream") + playsound(src, 'sound/machines/fryer/deep_fryer_emerge.ogg', 50) + if(iscarbon(owner)) //Type safety for if a drone somehow got a shield (ratvar protect us) + var/mob/living/carbon/C = owner + var/obj/item/bodypart/part = C.get_holding_bodypart_of_item(src) + C.apply_damage((iscultist(C) ? damage * 2 : damage), BURN, (istype(part, /obj/item/bodypart/l_arm) ? BODY_ZONE_L_ARM : BODY_ZONE_R_ARM)) //Deals the damage to the holder instead of absorbing it instead + forcedrops. Doubled if a cultist of Nar'Sie. + else + owner.adjustFireLoss(iscultist(owner) ? damage * 2 : damage) + addtimer(CALLBACK(owner, /mob/living.proc/dropItemToGround, src, TRUE), 1) + else if(!is_servant_of_ratvar(attacker)) //No exploiting my snowflake mechanics + dam_absorbed += damage + playsound(owner, 'sound/machines/clockcult/steam_whoosh.ogg', 30) + + if(damage <= 10) //The shield itself is hard to break, this DOES NOT modify the actual blocking-mechanic + damage = 0 + else + damage -= 5 + return ..() + +/obj/item/shield/riot/ratvarian/shatter(mob/living/carbon/human/owner) + playsound(owner, 'sound/magic/clockwork/anima_fragment_death.ogg', 50) + new /obj/item/clockwork/alloy_shards/large(get_turf(src)) + +/obj/item/shield/riot/ratvarian/user_shieldbash(mob/living/user, atom/target, harmful) + if(!harmful || !is_servant_of_ratvar(user)) // No fun for non-clockies, but you can keep the normal bashes. Until you try to block with it. + shieldbash_knockback = initial(shieldbash_knockback) + shieldbash_brutedamage = initial(shieldbash_brutedamage) //Prevention for funky stuff that might happen otherwise + shieldbash_stamdmg = initial(shieldbash_stamdmg) + return ..() + var/actual_bash_mult = calc_bash_mult() + shieldbash_knockback = round(initial(shieldbash_knockback) * actual_bash_mult, 1) //Modifying the strength of the bash, done with initial() to prevent magic-number issues if the original shieldbash values are changed + shieldbash_brutedamage = round(initial(shieldbash_brutedamage) * actual_bash_mult, 1) //Where I think of it, better round this stuff because we don't need even more things that deal like 3.25 damage + shieldbash_stamdmg = round(initial(shieldbash_stamdmg) * actual_bash_mult, 1) //Like 20 brute and 60 stam + a fuckton of knockback at the moment (at maximum charge), seems mostly fine? I think? + . = ..() + if(.) //If this bash actually hit someone + if(actual_bash_mult > 1) + playsound(user, 'sound/magic/fireball.ogg', 50, TRUE, frequency = 1.25) + dam_absorbed -= calc_bash_absorb_use() + return diff --git a/code/modules/antagonists/clockcult/clock_items/soul_vessel.dm b/code/modules/antagonists/clockcult/clock_items/soul_vessel.dm index f83afebe24..6bec6e3bc7 100644 --- a/code/modules/antagonists/clockcult/clock_items/soul_vessel.dm +++ b/code/modules/antagonists/clockcult/clock_items/soul_vessel.dm @@ -31,6 +31,7 @@ laws = new /datum/ai_laws/ratvar() braintype = picked_name GLOB.all_clockwork_objects += src + brainmob.add_blocked_language(subtypesof(/datum/language) - /datum/language/ratvar, LANGUAGE_CLOCKIE) /obj/item/mmi/posibrain/soul_vessel/Destroy() GLOB.all_clockwork_objects -= src diff --git a/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm b/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm index f43f2814d8..dd37f3727c 100644 --- a/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm +++ b/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm @@ -17,7 +17,8 @@ obj_damage = 40 melee_damage_lower = 12 melee_damage_upper = 12 - attacktext = "slashes" + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" attack_sound = 'sound/weapons/bladeslice.ogg' weather_immunities = list("lava") movement_type = FLYING @@ -68,14 +69,16 @@ maxHealth = 300 melee_damage_upper = 25 melee_damage_lower = 25 - attacktext = "devastates" + attack_verb_continuous = "devastates" + attack_verb_simple = "devastate" speed = -1 obj_damage = 100 max_shield_health = INFINITY else if(GLOB.ratvar_approaches) //Hefty health bonus and slight attack damage increase melee_damage_upper = 15 melee_damage_lower = 15 - attacktext = "carves" + attack_verb_continuous = "carves" + attack_verb_simple = "carve" obj_damage = 50 max_shield_health = 4 diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm index 130fc24583..c40168a986 100644 --- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm +++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm @@ -100,6 +100,24 @@ quickbind = TRUE quickbind_desc = "Creates a Judicial Visor, which can smite an area, applying Belligerent and briefly stunning." +//Nezbere's shield: Creates a ratvarian shield which absorbs attacks, see ratvarian_shield.dm for details. +/datum/clockwork_scripture/create_object/nezberes_shield + descname = "Shield with empowerable bashes" + name = "Nezbere's shield" + desc = "Creates a shield which generates charge from blocking damage, using it to empower its bashes tremendously. It is repaired with brass, and while very durable, extremely weak to lasers and, even more so, to energy weaponry." + invocations = list("Shield me...", "... from the coming dark!") + channel_time = 20 + power_cost = 600 //Shouldn't be too spammable but not too hard to get either + whispered = TRUE + creator_message = "You form a ratvarian shield, which is capable of absorbing blocked attacks to empower its bashes." + object_path = /obj/item/shield/riot/ratvarian + usage_tip = "Bashes will only use charge when performed with intent to harm." + tier = SCRIPTURE_SCRIPT + space_allowed = TRUE + primary_component = VANGUARD_COGWHEEL + sort_priority = 5 + quickbind = TRUE + quickbind_desc = "Creates a Ratvarian shield, which can absorb energy from attacks for use in powerful bashes." //Clockwork Armaments: Grants the invoker the ability to call forth a Ratvarian spear and clockwork armor. /datum/clockwork_scripture/clockwork_armaments @@ -113,7 +131,7 @@ usage_tip = "Throwing the spear at a mob will do massive damage and knock them down, but break the spear. You will need to wait for 30 seconds before resummoning it." tier = SCRIPTURE_SCRIPT primary_component = VANGUARD_COGWHEEL - sort_priority = 5 + sort_priority = 6 important = TRUE quickbind = TRUE quickbind_desc = "Permanently binds clockwork armor and a Ratvarian spear to you." @@ -213,7 +231,7 @@ usage_tip = "This gateway is strictly one-way and will only allow things through the invoker's portal." tier = SCRIPTURE_SCRIPT primary_component = GEIS_CAPACITOR - sort_priority = 6 + sort_priority = 7 quickbind = TRUE quickbind_desc = "Allows you to create a one-way Spatial Gateway to a living Servant or Clockwork Obelisk." diff --git a/code/modules/antagonists/clockcult/clockcult.dm b/code/modules/antagonists/clockcult/clockcult.dm index cbfd443744..b6ed7dfe65 100644 --- a/code/modules/antagonists/clockcult/clockcult.dm +++ b/code/modules/antagonists/clockcult/clockcult.dm @@ -5,6 +5,7 @@ antagpanel_category = "Clockcult" job_rank = ROLE_SERVANT_OF_RATVAR antag_moodlet = /datum/mood_event/cult + skill_modifiers = list(/datum/skill_modifier/job/level/wiring) var/datum/action/innate/hierophant/hierophant_network = new threat = 3 var/datum/team/clockcult/clock_team @@ -91,7 +92,7 @@ current = mob_override GLOB.all_clockwork_mobs += current current.faction |= "ratvar" - current.grant_language(/datum/language/ratvar) + current.grant_language(/datum/language/ratvar, TRUE, TRUE, LANGUAGE_CLOCKIE) current.update_action_buttons_icon() //because a few clockcult things are action buttons and we may be wearing/holding them for whatever reason, we need to update buttons if(issilicon(current)) var/mob/living/silicon/S = current @@ -102,6 +103,7 @@ R.module.rebuild_modules() else if(isAI(S)) var/mob/living/silicon/ai/A = S + A.add_blocked_language(subtypesof(/datum/language) - /datum/language/ratvar, LANGUAGE_CLOCKIE) A.can_be_carded = FALSE A.requires_power = POWER_REQ_CLOCKCULT var/list/AI_frame = list(mutable_appearance('icons/mob/clockwork_mobs.dmi', "aiframe")) //make the AI's cool frame @@ -142,7 +144,7 @@ current = mob_override GLOB.all_clockwork_mobs -= current current.faction -= "ratvar" - current.remove_language(/datum/language/ratvar) + current.remove_language(/datum/language/ratvar, TRUE, TRUE, LANGUAGE_CLOCKIE) current.clear_alert("clockinfo") for(var/datum/action/innate/clockwork_armaments/C in owner.current.actions) //Removes any bound clockwork armor qdel(C) @@ -152,6 +154,7 @@ var/mob/living/silicon/S = current if(isAI(S)) var/mob/living/silicon/ai/A = S + A.remove_blocked_language(subtypesof(/datum/language) - /datum/language/ratvar, LANGUAGE_CLOCKIE) A.can_be_carded = initial(A.can_be_carded) A.requires_power = initial(A.requires_power) A.cut_overlays() diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm index ae61b2c814..87e116166e 100644 --- a/code/modules/antagonists/cult/cult.dm +++ b/code/modules/antagonists/cult/cult.dm @@ -116,7 +116,7 @@ if(mob_override) current = mob_override current.faction |= "cult" - current.grant_language(/datum/language/narsie) + current.grant_language(/datum/language/narsie, TRUE, TRUE, LANGUAGE_CULTIST) if(!cult_team?.cult_master) vote.Grant(current) communion.Grant(current) @@ -134,7 +134,7 @@ if(mob_override) current = mob_override current.faction -= "cult" - current.remove_language(/datum/language/narsie) + current.remove_language(/datum/language/narsie, TRUE, TRUE, LANGUAGE_CULTIST) vote.Remove(current) communion.Remove(current) magic.Remove(current) diff --git a/code/modules/antagonists/devil/devil.dm b/code/modules/antagonists/devil/devil.dm index a7071276cc..c12259778e 100644 --- a/code/modules/antagonists/devil/devil.dm +++ b/code/modules/antagonists/devil/devil.dm @@ -183,7 +183,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", if(soulsOwned.Find(soul)) return soulsOwned += soul - owner.current.nutrition = NUTRITION_LEVEL_FULL + owner.current.set_nutrition(NUTRITION_LEVEL_FULL) to_chat(owner.current, "You feel satiated as you received a new soul.") update_hud() switch(SOULVALUE) @@ -527,7 +527,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", /datum/antagonist/devil/apply_innate_effects(mob/living/mob_override) give_appropriate_spells() - owner.current.grant_all_languages(TRUE) + owner.current.grant_all_languages(TRUE, TRUE, TRUE, LANGUAGE_DEVIL) update_hud() .=..() @@ -536,6 +536,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", var/obj/effect/proc_holder/spell/S = X if(is_type_in_typecache(S, devil_spells)) owner.RemoveSpell(S) + owner.current.remove_all_languages(LANGUAGE_DEVIL) .=..() /datum/antagonist/devil/proc/printdevilinfo() diff --git a/code/modules/antagonists/devil/imp/imp.dm b/code/modules/antagonists/devil/imp/imp.dm index 1539bc384b..7a6850bfa1 100644 --- a/code/modules/antagonists/devil/imp/imp.dm +++ b/code/modules/antagonists/devil/imp/imp.dm @@ -7,9 +7,12 @@ desc = "A large, menacing creature covered in armored black scales." speak_emote = list("cackles") emote_hear = list("cackles","screeches") - response_help = "thinks better of touching" - response_disarm = "flails at" - response_harm = "punches" + response_help_continuous = "thinks better of touching" + response_help_simple = "think better of touching" + response_disarm_continuous = "flails at" + response_disarm_simple = "flail at" + response_harm_continuous = "punches" + response_harm_simple = "punch" icon = 'icons/mob/mob.dmi' icon_state = "imp" icon_living = "imp" @@ -23,7 +26,8 @@ minbodytemp = 250 //Weak to cold maxbodytemp = INFINITY faction = list("hell") - attacktext = "wildly tears into" + attack_verb_continuous = "wildly tears into" + attack_verb_simple = "wildly tear into" maxHealth = 200 health = 200 healable = 0 diff --git a/code/modules/antagonists/devil/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm index 5725ac137b..1b245b5a01 100644 --- a/code/modules/antagonists/devil/true_devil/_true_devil.dm +++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm @@ -29,7 +29,7 @@ /mob/living/carbon/true_devil/Initialize() create_bodyparts() //initialize bodyparts create_internal_organs() - grant_all_languages(omnitongue=TRUE) + grant_all_languages() ..() /mob/living/carbon/true_devil/create_internal_organs() diff --git a/code/modules/antagonists/ert/ert.dm b/code/modules/antagonists/ert/ert.dm index bda1fbabe6..1d773627c7 100644 --- a/code/modules/antagonists/ert/ert.dm +++ b/code/modules/antagonists/ert/ert.dm @@ -51,6 +51,7 @@ /datum/antagonist/ert/engineer role = "Engineer" outfit = /datum/outfit/ert/engineer + skill_modifiers = list(/datum/skill_modifier/job/level/wiring) /datum/antagonist/ert/engineer/amber outfit = /datum/outfit/ert/engineer/alert @@ -61,6 +62,7 @@ /datum/antagonist/ert/medic role = "Medical Officer" outfit = /datum/outfit/ert/medic + skill_modifiers = list(/datum/skill_modifier/job/affinity/surgery) /datum/antagonist/ert/medic/amber outfit = /datum/outfit/ert/medic/alert diff --git a/code/modules/antagonists/morph/morph.dm b/code/modules/antagonists/morph/morph.dm index ad2eb4792a..e91feda006 100644 --- a/code/modules/antagonists/morph/morph.dm +++ b/code/modules/antagonists/morph/morph.dm @@ -28,7 +28,8 @@ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE vision_range = 1 // Only attack when target is close wander = FALSE - attacktext = "glomps" + attack_verb_continuous = "glomps" + attack_verb_simple = "glomp" attack_sound = 'sound/effects/blobattack.ogg' butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2) diff --git a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm index dc44a3b2d8..a11ecaa3df 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm @@ -451,9 +451,9 @@ return qdel(src) -/obj/machinery/nuclearbomb/tesla_act(power, tesla_flags) +/obj/machinery/nuclearbomb/zap_act(power, zap_flags) ..() - if(tesla_flags & TESLA_MACHINE_EXPLOSIVE) + if(zap_flags & ZAP_MACHINE_EXPLOSIVE) qdel(src)//like the singulo, tesla deletes it. stops it from exploding over and over #define NUKERANGE 127 @@ -606,6 +606,7 @@ This is here to make the tiles around the station mininuke change when it's arme lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi' icon_state = "datadisk0" + w_volume = ITEM_VOLUME_DISK /obj/item/disk/nuclear name = "nuclear authentication disk" diff --git a/code/modules/antagonists/nukeop/nukeop.dm b/code/modules/antagonists/nukeop/nukeop.dm index 7510ad6997..454cde6d72 100644 --- a/code/modules/antagonists/nukeop/nukeop.dm +++ b/code/modules/antagonists/nukeop/nukeop.dm @@ -5,6 +5,7 @@ job_rank = ROLE_OPERATIVE antag_moodlet = /datum/mood_event/focused threat = 10 + skill_modifiers = list(/datum/skill_modifier/job/level/wiring) var/datum/team/nuclear/nuke_team var/always_new_team = FALSE //If not assigned a team by default ops will try to join existing ones, set this to TRUE to always create new team. var/send_to_spawnpoint = TRUE //Should the user be moved to default spawnpoint. diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm index 2638a6a8e3..e06e8691b3 100644 --- a/code/modules/antagonists/revenant/revenant.dm +++ b/code/modules/antagonists/revenant/revenant.dm @@ -27,19 +27,24 @@ sight = SEE_SELF throwforce = 0 blood_volume = 0 + has_field_of_vision = FALSE //we are a spoopy ghost see_in_dark = 8 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE - response_help = "passes through" - response_disarm = "swings through" - response_harm = "punches through" + response_help_continuous = "passes through" + response_help_simple = "pass through" + response_disarm_continuous = "swings through" + response_disarm_simple = "swing through" + response_harm_continuous = "punches through" + response_harm_simple = "punch through" unsuitable_atmos_damage = 0 damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) //I don't know how you'd apply those, but revenants no-sell them anyway. atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 maxbodytemp = INFINITY harm_intent_damage = 0 - friendly = "touches" + friendly_verb_continuous = "touches" + friendly_verb_simple = "touch" status_flags = 0 wander = FALSE density = FALSE diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm index 5d409a7fb9..6b063559dc 100644 --- a/code/modules/antagonists/slaughter/slaughter.dm +++ b/code/modules/antagonists/slaughter/slaughter.dm @@ -6,9 +6,12 @@ desc = "A large, menacing creature covered in armored black scales." speak_emote = list("gurgles") emote_hear = list("wails","screeches") - response_help = "thinks better of touching" - response_disarm = "flails at" - response_harm = "punches" + response_help_continuous = "thinks better of touching" + response_help_simple = "think better of touching" + response_disarm_continuous = "flails at" + response_disarm_simple = "flail at" + response_harm_continuous = "punches" + response_harm_simple = "punch" icon = 'icons/mob/mob.dmi' icon_state = "daemon" icon_living = "daemon" @@ -24,7 +27,8 @@ minbodytemp = 0 maxbodytemp = INFINITY faction = list("slaughter") - attacktext = "wildly tears into" + attack_verb_continuous = "wildly tears into" + attack_verb_simple = "wildly tear into" maxHealth = 200 health = 200 healable = 0 @@ -116,8 +120,10 @@ desc = "A large, adorable creature covered in armor with pink bows." speak_emote = list("giggles","titters","chuckles") emote_hear = list("guffaws","laughs") - response_help = "hugs" - attacktext = "wildly tickles" + response_help_continuous = "hugs" + response_help_simple = "hug" + attack_verb_continuous = "wildly tickles" + attack_verb_simple = "wildly tickle" attack_sound = 'sound/items/bikehorn.ogg' feast_sound = 'sound/spookoween/scary_horn2.ogg' diff --git a/code/modules/antagonists/swarmer/swarmer.dm b/code/modules/antagonists/swarmer/swarmer.dm index c1f493ac52..d0e36394ab 100644 --- a/code/modules/antagonists/swarmer/swarmer.dm +++ b/code/modules/antagonists/swarmer/swarmer.dm @@ -84,9 +84,11 @@ hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD) obj_damage = 0 environment_smash = ENVIRONMENT_SMASH_NONE - attacktext = "shocks" + attack_verb_continuous = "shocks" + attack_verb_simple = "shock" attack_sound = 'sound/effects/empulse.ogg' - friendly = "pinches" + friendly_verb_continuous = "pinches" + friendly_verb_simple = "pinch" speed = 0 faction = list("swarmer") AIStatus = AI_OFF diff --git a/code/modules/antagonists/traitor/classes/ai.dm b/code/modules/antagonists/traitor/classes/ai.dm index eaa1137d51..f9682e5025 100644 --- a/code/modules/antagonists/traitor/classes/ai.dm +++ b/code/modules/antagonists/traitor/classes/ai.dm @@ -65,5 +65,5 @@ /datum/traitor_class/ai/finalize_traitor(datum/antagonist/traitor/T) T.add_law_zero() T.owner.current.playsound_local(get_turf(T.owner.current), 'sound/ambience/antag/malf.ogg', 100, FALSE, pressure_affected = FALSE) - T.owner.current.grant_language(/datum/language/codespeak) + T.owner.current.grant_language(/datum/language/codespeak, TRUE, TRUE, LANGUAGE_MALF) return FALSE diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 1d30cdbf77..4422f2f174 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -4,6 +4,7 @@ antagpanel_category = "Traitor" job_rank = ROLE_TRAITOR antag_moodlet = /datum/mood_event/focused + skill_modifiers = list(/datum/skill_modifier/job/level/wiring/basic) var/special_role = ROLE_TRAITOR var/employer = "The Syndicate" var/give_objectives = TRUE diff --git a/code/modules/antagonists/traitor/syndicate_contract.dm b/code/modules/antagonists/traitor/syndicate_contract.dm index daa9127591..70ff59eee0 100644 --- a/code/modules/antagonists/traitor/syndicate_contract.dm +++ b/code/modules/antagonists/traitor/syndicate_contract.dm @@ -78,14 +78,28 @@ var/mob/living/carbon/human/target = M // After we remove items, at least give them what they need to live. target.dna.species.give_important_for_life(target) handleVictimExperience(M) // After pod is sent we start the victim narrative/heal. - var/points_to_check = SSshuttle.points // This is slightly delayed because of the sleep calls above to handle the narrative. We don't want to tell the station instantly. - if(points_to_check >= ransom) - SSshuttle.points -= ransom - else - SSshuttle.points -= points_to_check + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + var/points_to_check = min(D.account_balance, ransom) + D.adjust_money(min(points_to_check, ransom)) priority_announce("One of your crew was captured by a rival organisation - we've needed to pay their ransom to bring them back. \ As is policy we've taken a portion of the station's funds to offset the overall cost.", null, "attention", null, "Nanotrasen Asset Protection") + sleep(30) + + // Pay contractor their portion of ransom + if (status == CONTRACT_STATUS_COMPLETE) + var/mob/living/carbon/human/H + var/obj/item/card/id/C + if(ishuman(contract.owner.current)) + H = contract.owner.current + C = H.get_idcard(TRUE) + + if(C && C.registered_account) + C.registered_account.adjust_money(points_to_check * 0.35) + + C.registered_account.bank_card_talk("We've processed the ransom, agent. Here's your cut - your balance is now \ + [C.registered_account.account_balance] cr.", TRUE) + /datum/syndicate_contract/proc/handleVictimExperience(var/mob/living/M) // They're off to holding - handle the return timer and give some text about what's going on. addtimer(CALLBACK(src, .proc/returnVictim, M), 4 MINUTES) // Ship 'em back - dead or alive... 4 minutes wait. if(M.stat != DEAD) //Even if they weren't the target, we're still treating them the same. diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm index d7f1046cd7..46961c0caf 100644 --- a/code/modules/antagonists/wizard/equipment/soulstone.dm +++ b/code/modules/antagonists/wizard/equipment/soulstone.dm @@ -233,7 +233,7 @@ newstruct.cancel_camera() -/obj/item/soulstone/proc/init_shade(mob/living/carbon/human/T, mob/U, vic = 0) +/obj/item/soulstone/proc/init_shade(mob/living/carbon/human/T, mob/user, vic = 0) new /obj/effect/decal/remains/human(T.loc) //Spawns a skeleton T.stop_sound_channel(CHANNEL_HEARTBEAT) T.invisibility = INVISIBILITY_ABSTRACT @@ -245,20 +245,23 @@ S.name = "Shade of [T.real_name]" S.real_name = "Shade of [T.real_name]" T.transfer_ckey(S) - S.language_holder = U.language_holder.copy(S) - if(U) - S.faction |= "[REF(U)]" //Add the master as a faction, allowing inter-mob cooperation - if(U && iscultist(U)) + S.copy_languages(T, LANGUAGE_MIND)//Copies the old mobs languages into the new mob holder. + S.copy_languages(user, LANGUAGE_MASTER) + S.update_atom_languages() + grant_all_languages(FALSE, FALSE, TRUE) //Grants omnitongue + if(user) + S.faction |= "[REF(user)]" //Add the master as a faction, allowing inter-mob cooperation + if(user && iscultist(user)) SSticker.mode.add_cultist(S.mind, 0) S.cancel_camera() name = "soulstone: Shade of [T.real_name]" icon_state = "soulstone2" - if(U && (iswizard(U) || usability)) - to_chat(S, "Your soul has been captured! You are now bound to [U.real_name]'s will. Help [U.p_them()] succeed in [U.p_their()] goals at all costs.") - else if(U && iscultist(U)) + if(user && (iswizard(user) || usability)) + to_chat(S, "Your soul has been captured! You are now bound to [user.real_name]'s will. Help [user.p_them()] succeed in [user.p_their()] goals at all costs.") + else if(user && iscultist(user)) to_chat(S, "Your soul has been captured! You are now bound to the cult's will. Help them succeed in their goals at all costs.") - if(vic && U) - to_chat(U, "Capture successful!: [T.real_name]'s soul has been ripped from [T.p_their()] body and stored within the soul stone.") + if(vic && user) + to_chat(user, "Capture successful!: [T.real_name]'s soul has been ripped from [T.p_their()] body and stored within the soul stone.") /obj/item/soulstone/proc/getCultGhost(mob/living/carbon/human/T, mob/U) diff --git a/code/modules/antagonists/wizard/equipment/spellbook.dm b/code/modules/antagonists/wizard/equipment/spellbook.dm index d49a8f83c6..a9bc64a932 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook.dm @@ -226,7 +226,11 @@ /datum/spellbook_entry/lightningbolt/Buy(mob/living/carbon/human/user,obj/item/spellbook/book) //return 1 on success . = ..() - user.flags_1 |= TESLA_IGNORE_1 + ADD_TRAIT(user, TRAIT_TESLA_SHOCKIMMUNE, "lightning_bolt_spell") + +/datum/spellbook_entry/lightningbolt/Refund(mob/living/carbon/human/user, obj/item/spellbook/book) + . = ..() + REMOVE_TRAIT(user, TRAIT_TESLA_SHOCKIMMUNE, "lightning_bolt_spell") /datum/spellbook_entry/infinite_guns name = "Lesser Summon Guns" diff --git a/modular_citadel/code/modules/arousal/arousal.dm b/code/modules/arousal/arousal.dm similarity index 99% rename from modular_citadel/code/modules/arousal/arousal.dm rename to code/modules/arousal/arousal.dm index 44eafc5fc6..c9b2690784 100644 --- a/modular_citadel/code/modules/arousal/arousal.dm +++ b/code/modules/arousal/arousal.dm @@ -63,7 +63,7 @@ if(!target || !R) return var/turfing = isturf(target) - G.generate_fluid() + G.generate_fluid(R) if(spill && R.total_volume >= 5) R.reaction(turfing ? target : target.loc, TOUCH, 1, 0) if(!turfing) diff --git a/modular_citadel/code/modules/arousal/genitals.dm b/code/modules/arousal/genitals.dm similarity index 99% rename from modular_citadel/code/modules/arousal/genitals.dm rename to code/modules/arousal/genitals.dm index 731c69a457..fb254a2dcc 100644 --- a/modular_citadel/code/modules/arousal/genitals.dm +++ b/code/modules/arousal/genitals.dm @@ -159,10 +159,10 @@ if(fluid_id && CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION)) time_since_last_orgasm++ -/obj/item/organ/genital/proc/generate_fluid() +/obj/item/organ/genital/proc/generate_fluid(datum/reagents/R) var/amount = clamp(fluid_rate * time_since_last_orgasm * fluid_mult,0,fluid_max_volume) - reagents.clear_reagents() - reagents.add_reagent(fluid_id,amount) + R.clear_reagents() + R.add_reagent(fluid_id,amount) return TRUE /obj/item/organ/genital/proc/update_link() diff --git a/modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm b/code/modules/arousal/genitals_sprite_accessories.dm similarity index 85% rename from modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm rename to code/modules/arousal/genitals_sprite_accessories.dm index 1cea2dd916..1140a1d3ec 100644 --- a/modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm +++ b/code/modules/arousal/genitals_sprite_accessories.dm @@ -9,7 +9,7 @@ //DICKS,COCKS,PENISES,WHATEVER YOU WANT TO CALL THEM /datum/sprite_accessory/penis - icon = 'modular_citadel/icons/obj/genitals/penis_onmob.dmi' + icon = 'icons/obj/genitals/penis_onmob.dmi' name = "penis" //the preview name of the accessory color_src = "cock_color" alt_aroused = TRUE @@ -22,13 +22,13 @@ /datum/sprite_accessory/penis/knotted icon_state = "knotted" name = "Knotted" - taur_icon = 'modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi' + taur_icon = 'icons/obj/genitals/taur_penis_onmob.dmi' taur_dimension_x = 64 /datum/sprite_accessory/penis/flared icon_state = "flared" name = "Flared" - taur_icon = 'modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi' + taur_icon = 'icons/obj/genitals/taur_penis_onmob.dmi' taur_dimension_x = 64 /datum/sprite_accessory/penis/barbknot @@ -38,7 +38,7 @@ /datum/sprite_accessory/penis/tapered icon_state = "tapered" name = "Tapered" - taur_icon = 'modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi' + taur_icon = 'icons/obj/genitals/taur_penis_onmob.dmi' taur_dimension_x = 64 /datum/sprite_accessory/penis/tentacle @@ -55,7 +55,7 @@ //Testicles /datum/sprite_accessory/testicles - icon = 'modular_citadel/icons/obj/genitals/testicles_onmob.dmi' + icon = 'icons/obj/genitals/testicles_onmob.dmi' icon_state = "testicle" name = "testicle" //the preview name of the accessory color_src = "balls_color" @@ -66,7 +66,7 @@ //Vaginas /datum/sprite_accessory/vagina - icon = 'modular_citadel/icons/obj/genitals/vagina_onmob.dmi' + icon = 'icons/obj/genitals/vagina_onmob.dmi' name = "vagina" color_src = "vag_color" alt_aroused = TRUE @@ -104,7 +104,7 @@ //BREASTS BE HERE /datum/sprite_accessory/breasts - icon = 'modular_citadel/icons/obj/genitals/breasts_onmob.dmi' + icon = 'icons/obj/genitals/breasts_onmob.dmi' name = "breasts" color_src = "breasts_color" diff --git a/modular_citadel/code/modules/arousal/organs/breasts.dm b/code/modules/arousal/organs/breasts.dm similarity index 98% rename from modular_citadel/code/modules/arousal/organs/breasts.dm rename to code/modules/arousal/organs/breasts.dm index 213ebb049a..0989966638 100644 --- a/modular_citadel/code/modules/arousal/organs/breasts.dm +++ b/code/modules/arousal/organs/breasts.dm @@ -5,7 +5,7 @@ name = "breasts" desc = "Female milk producing organs." icon_state = "breasts" - icon = 'modular_citadel/icons/obj/genitals/breasts.dmi' + icon = 'icons/obj/genitals/breasts.dmi' zone = BODY_ZONE_CHEST slot = ORGAN_SLOT_BREASTS size = BREASTS_SIZE_DEF // "c". Refer to the breast_values static list below for the cups associated number values diff --git a/modular_citadel/code/modules/arousal/organs/penis.dm b/code/modules/arousal/organs/penis.dm similarity index 97% rename from modular_citadel/code/modules/arousal/organs/penis.dm rename to code/modules/arousal/organs/penis.dm index e1b8dc0dba..7b20c0e7ce 100644 --- a/modular_citadel/code/modules/arousal/organs/penis.dm +++ b/code/modules/arousal/organs/penis.dm @@ -2,7 +2,7 @@ name = "penis" desc = "A male reproductive organ." icon_state = "penis" - icon = 'modular_citadel/icons/obj/genitals/penis.dmi' + icon = 'icons/obj/genitals/penis.dmi' zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_PENIS masturbation_verb = "stroke" diff --git a/modular_citadel/code/modules/arousal/organs/testicles.dm b/code/modules/arousal/organs/testicles.dm similarity index 97% rename from modular_citadel/code/modules/arousal/organs/testicles.dm rename to code/modules/arousal/organs/testicles.dm index 5fb1c75ad0..bfb5c99a55 100644 --- a/modular_citadel/code/modules/arousal/organs/testicles.dm +++ b/code/modules/arousal/organs/testicles.dm @@ -2,7 +2,7 @@ name = "testicles" desc = "A male reproductive organ." icon_state = "testicles" - icon = 'modular_citadel/icons/obj/genitals/testicles.dmi' + icon = 'icons/obj/genitals/testicles.dmi' zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_TESTICLES size = BALLS_SIZE_MIN diff --git a/modular_citadel/code/modules/arousal/organs/vagina.dm b/code/modules/arousal/organs/vagina.dm similarity index 97% rename from modular_citadel/code/modules/arousal/organs/vagina.dm rename to code/modules/arousal/organs/vagina.dm index cdc7dc4927..5c8bbeea98 100644 --- a/modular_citadel/code/modules/arousal/organs/vagina.dm +++ b/code/modules/arousal/organs/vagina.dm @@ -1,7 +1,7 @@ /obj/item/organ/genital/vagina name = "vagina" desc = "A female reproductive organ." - icon = 'modular_citadel/icons/obj/genitals/vagina.dmi' + icon = 'icons/obj/genitals/vagina.dmi' icon_state = ORGAN_SLOT_VAGINA zone = BODY_ZONE_PRECISE_GROIN slot = "vagina" diff --git a/modular_citadel/code/modules/arousal/organs/womb.dm b/code/modules/arousal/organs/womb.dm similarity index 84% rename from modular_citadel/code/modules/arousal/organs/womb.dm rename to code/modules/arousal/organs/womb.dm index 7f91310e3e..386f407a26 100644 --- a/modular_citadel/code/modules/arousal/organs/womb.dm +++ b/code/modules/arousal/organs/womb.dm @@ -1,7 +1,7 @@ /obj/item/organ/genital/womb name = "womb" desc = "A female reproductive organ." - icon = 'modular_citadel/icons/obj/genitals/vagina.dmi' + icon = 'icons/obj/genitals/vagina.dmi' icon_state = "womb" zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_WOMB diff --git a/modular_citadel/code/modules/arousal/toys/dildos.dm b/code/modules/arousal/toys/dildos.dm similarity index 98% rename from modular_citadel/code/modules/arousal/toys/dildos.dm rename to code/modules/arousal/toys/dildos.dm index 58245c0c5f..5cb6d47118 100644 --- a/modular_citadel/code/modules/arousal/toys/dildos.dm +++ b/code/modules/arousal/toys/dildos.dm @@ -4,7 +4,7 @@ /obj/item/dildo name = "dildo" desc = "Floppy!" - icon = 'modular_citadel/icons/obj/genitals/dildo.dmi' + icon = 'icons/obj/genitals/dildo.dmi' force = 0 hitsound = 'sound/weapons/tap.ogg' throwforce = 0 diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index 632542f605..081f0b1d28 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -89,7 +89,7 @@ temperature_archived = temperature /turf/open/archive() - ARCHIVE_TEMPERATURE(air) + ARCHIVE(air) archived_cycle = SSair.times_fired temperature_archived = temperature @@ -215,7 +215,7 @@ if (planet_atmos) //share our air with the "atmosphere" "above" the turf var/datum/gas_mixture/G = new G.copy_from_turf(src) - ARCHIVE_TEMPERATURE(G) + ARCHIVE(G) if(our_air.compare(G)) if(!our_excited_group) var/datum/excited_group/EG = new diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index 5ff8586c34..93927f4420 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -17,6 +17,7 @@ GLOBAL_LIST_INIT(meta_gas_ids, meta_gas_id_list()) GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) /datum/gas_mixture var/list/gases = list() + var/list/gas_archive = list() var/temperature = 0 //kelvins var/tmp/temperature_archived = 0 var/volume = CELL_VOLUME //liters @@ -31,13 +32,25 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) //PV = nRT -/datum/gas_mixture/proc/heat_capacity() //joules per kelvin +/datum/gas_mixture/proc/heat_capacity() + +/datum/gas_mixture/proc/archived_heat_capacity() + +/datum/gas_mixture/heat_capacity() //joules per kelvin var/list/cached_gases = gases var/list/cached_gasheats = GLOB.meta_gas_specific_heats . = 0 for(var/id in cached_gases) . += cached_gases[id] * cached_gasheats[id] +/datum/gas_mixture/archived_heat_capacity() + // lots of copypasta but heat_capacity is the single proc called the most in a regular round, bar none, so performance loss adds up + var/list/cached_gases = gas_archive + var/list/cached_gasheats = GLOB.meta_gas_specific_heats + . = 0 + for(var/id in cached_gases) + . += cached_gases[id] * cached_gasheats[id] + /datum/gas_mixture/turf/heat_capacity() // Same as above except vacuums return HEAT_CAPACITY_VACUUM var/list/cached_gases = gases var/list/cached_gasheats = GLOB.meta_gas_specific_heats @@ -46,6 +59,14 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) if(!.) . += HEAT_CAPACITY_VACUUM //we want vacuums in turfs to have the same heat capacity as space +/datum/gas_mixture/turf/archived_heat_capacity() // Same as above except vacuums return HEAT_CAPACITY_VACUUM + var/list/cached_gases = gas_archive + var/list/cached_gasheats = GLOB.meta_gas_specific_heats + for(var/id in cached_gases) + . += cached_gases[id] * cached_gasheats[id] + if(!.) + . += HEAT_CAPACITY_VACUUM //we want vacuums in turfs to have the same heat capacity as space + /datum/gas_mixture/proc/total_moles() var/cached_gases = gases TOTAL_MOLES(cached_gases, .) @@ -67,6 +88,10 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) /datum/gas_mixture/proc/thermal_energy() //joules return THERMAL_ENERGY(src) //see code/__DEFINES/atmospherics.dm; use the define in performance critical areas +/datum/gas_mixture/proc/archive() + //Update archived versions of variables + //Returns: 1 in all cases + /datum/gas_mixture/proc/merge(datum/gas_mixture/giver) //Merges all air from giver into self. Deletes giver. //Returns: 1 if we are mutable, 0 otherwise @@ -111,6 +136,10 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) //Performs various reactions such as combustion or fusion (LOL) //Returns: 1 if any reaction took place; 0 otherwise +/datum/gas_mixture/archive() + temperature_archived = temperature + gas_archive = gases.Copy() + return 1 /datum/gas_mixture/merge(datum/gas_mixture/giver) if(!giver) @@ -245,7 +274,7 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) //GAS TRANSFER for(var/id in cached_gases | sharer_gases) // transfer gases - delta = QUANTIZE(cached_gases[id] - sharer_gases[id])/(atmos_adjacent_turfs+1) //the amount of gas that gets moved between the mixtures + delta = QUANTIZE(gas_archive[id] - sharer.gas_archive[id])/(atmos_adjacent_turfs+1) //the amount of gas that gets moved between the mixtures if(delta && abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) gas_heat_capacity = delta * cached_gasheats[id] @@ -293,8 +322,8 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) sharer_temperature = sharer.temperature_archived var/temperature_delta = temperature_archived - sharer_temperature if(abs(temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity() - sharer_heat_capacity = sharer_heat_capacity || sharer.heat_capacity() + var/self_heat_capacity = archived_heat_capacity() + sharer_heat_capacity = sharer_heat_capacity || sharer.archived_heat_capacity() if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) var/heat = conduction_coefficient*temperature_delta* \ diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm index a4617462fe..733c760855 100644 --- a/code/modules/atmospherics/machinery/airalarm.dm +++ b/code/modules/atmospherics/machinery/airalarm.dm @@ -36,6 +36,7 @@ /obj/item/electronics/airalarm name = "air alarm electronics" icon_state = "airalarm_electronics" + custom_price = 50 /obj/item/wallframe/airalarm name = "air alarm frame" @@ -66,6 +67,7 @@ desc = "A machine that monitors atmosphere levels. Goes off if the area is dangerous." icon = 'icons/obj/monitors.dmi' icon_state = "alarm0" + plane = ABOVE_WALL_PLANE use_power = IDLE_POWER_USE idle_power_usage = 4 active_power_usage = 8 @@ -786,9 +788,8 @@ return user.visible_message("[user.name] wires the air alarm.", \ "You start wiring the air alarm...") - if (do_after(user, 20, target = src)) - if (cable.get_amount() >= 5 && buildstage == 1) - cable.use(5) + if (W.use_tool(src, user, 20, 5)) + if (buildstage == 1) to_chat(user, "You wire the air alarm.") wires.repair() aidisabled = 0 diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index 8f5ab7dd5e..97389848ba 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -17,6 +17,7 @@ active_power_usage = 0 power_channel = ENVIRON layer = GAS_PIPE_HIDDEN_LAYER //under wires + plane = ABOVE_WALL_PLANE resistance_flags = FIRE_PROOF max_integrity = 200 obj_flags = CAN_BE_HIT | ON_BLUEPRINTS diff --git a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm index c164dc5ae3..6b685d4bc1 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm @@ -7,6 +7,7 @@ name = "circulator/heat exchanger" desc = "A gas circulator pump and heat exchanger." icon_state = "circ-off-0" + plane = GAME_PLANE var/active = FALSE diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm index a45728d51f..c229a4ba27 100644 --- a/code/modules/atmospherics/machinery/components/components_base.dm +++ b/code/modules/atmospherics/machinery/components/components_base.dm @@ -32,7 +32,7 @@ var/turf/T = loc if(level == 2 || (istype(T) && !T.intact)) showpipe = TRUE - plane = GAME_PLANE + plane = ABOVE_WALL_PLANE else showpipe = FALSE plane = FLOOR_PLANE diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 38042fe64d..4f26a2f772 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -6,6 +6,7 @@ max_integrity = 350 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 30, "acid" = 30) layer = ABOVE_WINDOW_LAYER + plane = GAME_PLANE state_open = FALSE circuit = /obj/item/circuitboard/machine/cryo_tube pipe_flags = PIPING_ONE_PER_TURF | PIPING_DEFAULT_LAYER_ONLY @@ -15,8 +16,8 @@ var/volume = 100 var/efficiency = 1 - var/sleep_factor = 0.00125 - var/unconscious_factor = 0.001 + var/base_knockout = 30 SECONDS + var/knockout_factor = 1 var/heat_capacity = 20000 var/conduction_coefficient = 0.3 @@ -33,6 +34,9 @@ var/message_cooldown var/breakout_time = 300 + fair_market_price = 10 + payment_department = ACCOUNT_MED + /obj/machinery/atmospherics/components/unary/cryo_cell/Initialize() . = ..() initialize_directions = dir @@ -50,10 +54,9 @@ var/C for(var/obj/item/stock_parts/matter_bin/M in component_parts) C += M.rating - + // 2 bins total, so C ranges from 2 to 8. efficiency = initial(efficiency) * C - sleep_factor = initial(sleep_factor) * C - unconscious_factor = initial(unconscious_factor) * C + knockout_factor = initial(knockout_factor) / max(1, (C * 0.33)) heat_capacity = initial(heat_capacity) / C conduction_coefficient = initial(conduction_coefficient) * C @@ -149,6 +152,9 @@ add_overlay("cover-on") addtimer(CALLBACK(src, .proc/run_anim, anim_up, occupant_overlay), 7, TIMER_UNIQUE) +/obj/machinery/atmospherics/components/unary/cryo_cell/nap_violation(mob/violator) + open_machine() + /obj/machinery/atmospherics/components/unary/cryo_cell/process() ..() @@ -162,7 +168,8 @@ return var/mob/living/mob_occupant = occupant - + if(!check_nap_violations()) + return if(mob_occupant.stat == DEAD) // We don't bother with dead people. return @@ -181,8 +188,10 @@ if(air1.gases.len) if(mob_occupant.bodytemperature < T0C) // Sleepytime. Why? More cryo magic. - mob_occupant.Sleeping((mob_occupant.bodytemperature * sleep_factor) * 2000) - mob_occupant.Unconscious((mob_occupant.bodytemperature * unconscious_factor) * 2000) + // temperature factor goes from 1 to about 2.5 + var/amount = max(1, (4 * log(T0C - mob_occupant.bodytemperature)) - 20) * knockout_factor * base_knockout + mob_occupant.Sleeping(amount) + mob_occupant.Unconscious(amount) if(beaker) if(reagent_transfer == 0) // Magically transfer reagents. Because cryo magic. beaker.reagents.trans_to(occupant, 1, efficiency * 0.25) // Transfer reagents. diff --git a/code/modules/atmospherics/machinery/components/unary_devices/tank.dm b/code/modules/atmospherics/machinery/components/unary_devices/tank.dm index c1bd59f49b..79ff24e8b7 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/tank.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/tank.dm @@ -7,6 +7,7 @@ max_integrity = 800 density = TRUE layer = ABOVE_WINDOW_LAYER + plane = GAME_PLANE pipe_flags = PIPING_ONE_PER_TURF var/volume = 10000 //in liters var/gas_type = 0 diff --git a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm index dddfdf08c1..7af3e57bc7 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm @@ -9,6 +9,7 @@ max_integrity = 300 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 30) layer = OBJ_LAYER + plane = GAME_PLANE circuit = /obj/item/circuitboard/machine/thermomachine ui_x = 300 ui_y = 230 diff --git a/code/modules/cargo/bounties/medical.dm b/code/modules/cargo/bounties/medical.dm index 7afc0d8786..c1f8d9c9d0 100644 --- a/code/modules/cargo/bounties/medical.dm +++ b/code/modules/cargo/bounties/medical.dm @@ -121,7 +121,7 @@ /datum/bounty/item/medical/defibrillator name = "New defibillators" - description = "After years of storge our defib units have become liabilities. Please send us some new ones." + description = "After years of storage our defibrillation units have worn out. Please send us some new ones." reward = 2250 required_count = 5 wanted_types = list(/obj/item/defibrillator) diff --git a/code/modules/cargo/bounties/science.dm b/code/modules/cargo/bounties/science.dm index ad03b2f393..a4632f7ed0 100644 --- a/code/modules/cargo/bounties/science.dm +++ b/code/modules/cargo/bounties/science.dm @@ -55,7 +55,7 @@ /datum/bounty/item/science/advanced_mop name = "Advanced Mop" - description = "Excuse me. I'd like to request 17 credits for a push broom rebristling. Either that, or an advanced mop." + description = "Excuse me. I'd like to request 17 cr for a push broom rebristling. Either that, or an advanced mop." reward = 3000 wanted_types = list(/obj/item/mop/advanced) diff --git a/code/modules/cargo/bounty.dm b/code/modules/cargo/bounty.dm index bfd97e4d1f..b888dc1a28 100644 --- a/code/modules/cargo/bounty.dm +++ b/code/modules/cargo/bounty.dm @@ -21,7 +21,9 @@ GLOBAL_LIST_EMPTY(bounties_list) // Called when the claim button is clicked. Override to provide fancy rewards. /datum/bounty/proc/claim() if(can_claim()) - SSshuttle.points += reward + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + if(D) + D.adjust_money(reward) claimed = TRUE // If an item sent in the cargo shuttle can satisfy the bounty. @@ -126,11 +128,11 @@ GLOBAL_LIST_EMPTY(bounties_list) /proc/setup_bounties() var/pick // instead of creating it a bunch let's go ahead and toss it here, we know we're going to use it for dynamics and subtypes! - + /********************************Subtype Gens********************************/ var/list/easy_add_list_subtypes = list(/datum/bounty/item/assistant = 2, - /datum/bounty/item/mech = 1, - /datum/bounty/item/chef = 2, + /datum/bounty/item/mech = 1, + /datum/bounty/item/chef = 2, /datum/bounty/item/security = 1, /datum/bounty/virus = 1, /datum/bounty/item/engineering = 1, @@ -139,30 +141,30 @@ GLOBAL_LIST_EMPTY(bounties_list) /datum/bounty/item/botany = 2, /datum/bounty/item/silly = 1, /datum/bounty/item/gardencook = 1) - + for(var/the_type in easy_add_list_subtypes) for(var/i in 1 to easy_add_list_subtypes[the_type]) pick = pick(subtypesof(the_type)) try_add_bounty(new pick) - + /********************************Strict Type Gens********************************/ var/list/easy_add_list_strict_types = list(/datum/bounty/reagent/simple_drink = 1, /datum/bounty/reagent/complex_drink = 1, /datum/bounty/reagent/chemical = 1) - + for(var/the_strict_type in easy_add_list_strict_types) for(var/i in 1 to easy_add_list_strict_types[the_strict_type]) try_add_bounty(new the_strict_type) - + /********************************Dynamic Gens********************************/ - + for(var/i in 0 to 1) if(prob(50)) pick = pick(subtypesof(/datum/bounty/item/slime)) else pick = pick(subtypesof(/datum/bounty/item/science)) try_add_bounty(new pick) - + /********************************Cutoff for Non-Low Priority Bounties********************************/ var/datum/bounty/B = pick(GLOB.bounties_list) B.mark_high_priority() @@ -172,7 +174,7 @@ GLOBAL_LIST_EMPTY(bounties_list) /datum/bounty/item/syndicate_documents, /datum/bounty/item/adamantine, /datum/bounty/more_bounties) - + for(var/low_priority_bounty in low_priority_strict_type_list) try_add_bounty(new low_priority_bounty) diff --git a/code/modules/cargo/bounty_console.dm b/code/modules/cargo/bounty_console.dm index 45260f4926..f499c38090 100644 --- a/code/modules/cargo/bounty_console.dm +++ b/code/modules/cargo/bounty_console.dm @@ -35,10 +35,10 @@ if(!GLOB.bounties_list.len) setup_bounties() - + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) var/list/dat = list({"Refresh Print Paper -

Credits: [SSshuttle.points]

+

Credits: [D.account_balance]

"}) for(var/datum/bounty/B in GLOB.bounties_list) diff --git a/code/modules/cargo/console.dm b/code/modules/cargo/console.dm index 64b208a90b..6968a5ccd8 100644 --- a/code/modules/cargo/console.dm +++ b/code/modules/cargo/console.dm @@ -3,6 +3,7 @@ desc = "Used to order supplies, approve requests, and control the shuttle." icon_screen = "supply" circuit = /obj/item/circuitboard/computer/cargo + req_access = list(ACCESS_CARGO) ui_x = 780 ui_y = 750 @@ -25,6 +26,7 @@ desc = "Used to request supplies from cargo." icon_screen = "request" circuit = /obj/item/circuitboard/computer/cargo/request + req_access = list() requestonly = TRUE /obj/machinery/computer/cargo/Initialize() @@ -49,6 +51,7 @@ . |= EXPORT_EMAG /obj/machinery/computer/cargo/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return if(user) @@ -62,7 +65,9 @@ var/obj/item/circuitboard/computer/cargo/board = circuit board.contraband = TRUE board.obj_flags |= EMAGGED + req_access = list() update_static_data(user) + return ..() /obj/machinery/computer/cargo/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) @@ -74,9 +79,12 @@ /obj/machinery/computer/cargo/ui_data() var/list/data = list() data["location"] = SSshuttle.supply.getStatusText() + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + if(D) + data["points"] = D.account_balance data["away"] = SSshuttle.supply.getDockedId() == "supply_away" + data["self_paid"] = self_paid data["docked"] = SSshuttle.supply.mode == SHUTTLE_IDLE - data["points"] = SSshuttle.points data["loan"] = !!SSshuttle.shuttle_loan data["loan_dispatched"] = SSshuttle.shuttle_loan && SSshuttle.shuttle_loan.dispatched var/message = "Remember to stamp and send back the supply manifests." @@ -92,6 +100,7 @@ "cost" = SO.pack.cost, "id" = SO.id, "orderer" = SO.orderer, + "paid" = !isnull(SO.paying_account) //paid by requester )) data["requests"] = list() @@ -110,6 +119,7 @@ var/list/data = list() data["requestonly"] = requestonly data["supplies"] = list() + data["emagged"] = obj_flags & EMAGGED for(var/pack in SSshuttle.supply_packs) var/datum/supply_pack/P = SSshuttle.supply_packs[pack] if(!data["supplies"][P.group]) @@ -124,13 +134,17 @@ "cost" = P.cost, "id" = pack, "desc" = P.desc || P.name, // If there is a description, use it. Otherwise use the pack's name. - "access" = P.access + "access" = P.access, + "can_private_buy" = P.can_private_buy )) return data /obj/machinery/computer/cargo/ui_act(action, params, datum/tgui/ui) if(..()) return + if(!allowed(usr)) + to_chat(usr, "Access denied.") + return switch(action) if("send") if(!SSshuttle.supply.canMove()) @@ -182,19 +196,34 @@ name = usr.real_name rank = "Silicon" + var/datum/bank_account/account + if(self_paid) + if(!pack.can_private_buy && !(obj_flags & EMAGGED)) + return + var/obj/item/card/id/id_card = usr.get_idcard(TRUE) + if(!istype(id_card)) + say("No ID card detected.") + return + account = id_card.registered_account + if(!istype(account)) + say("Invalid bank account.") + return + var/reason = "" - if(requestonly) + if(requestonly && !self_paid) reason = stripped_input("Reason:", name, "") if(isnull(reason) || ..()) return var/turf/T = get_turf(src) - var/datum/supply_order/SO = new(pack, name, rank, ckey, reason) + var/datum/supply_order/SO = new(pack, name, rank, ckey, reason, account) SO.generateRequisition(T) - if(requestonly) + if(requestonly && !self_paid) SSshuttle.requestlist += SO else SSshuttle.shoppinglist += SO + if(self_paid) + say("Order processed. The price will be charged to [account.account_holder]'s bank account on delivery.") . = TRUE if("remove") var/id = text2num(params["id"]) @@ -224,6 +253,9 @@ if("denyall") SSshuttle.requestlist.Cut() . = TRUE + if("toggleprivate") + self_paid = !self_paid + . = TRUE if(.) post_signal("supply") diff --git a/code/modules/cargo/exports.dm b/code/modules/cargo/exports.dm index bb90fa717a..671c22bde5 100644 --- a/code/modules/cargo/exports.dm +++ b/code/modules/cargo/exports.dm @@ -26,6 +26,7 @@ Credit dupes that require a lot of manual work shouldn't be removed, unless they var/list/total_value = list() //export instance => total value of sold objects var/list/reagents_volume = list()//export reagents => into the total volume of the object sold var/list/reagents_value = list()//export reagents => into the reagent type total value. + var/list/exported_atoms_ref = list() //if they're not deleted they go in here for use. // external_report works as "transaction" object, pass same one in if you're doing more than one export in single go /proc/export_item_and_contents(atom/movable/AM, allowed_categories = EXPORT_CARGO, apply_elastic = TRUE, delete_unsold = TRUE, dry_run=FALSE, datum/export_report/external_report) @@ -67,7 +68,7 @@ Credit dupes that require a lot of manual work shouldn't be removed, unless they var/unit_name = "" // Unit name. Only used in "Received [total_amount] [name]s [message]." message var/message = "" var/cost = 100 // Cost of item, in cargo credits. Must not alow for infinite price dupes, see above. - var/k_elasticity = 1/300 //coefficient used in marginal price calculation that roughly corresponds to the inverse of price elasticity, or "quantity elasticity" - CIT EDIT 1/30 - > 0 + var/k_elasticity = 1/100 //coefficient used in marginal price calculation that roughly corresponds to the inverse of price elasticity, or "quantity elasticity" - CIT EDIT 1/30 - > 100 var/list/export_types = list() // Type of the exported object. If none, the export datum is considered base type. var/include_subtypes = TRUE // Set to FALSE to make the datum apply only to a strict type. var/list/exclude_types = list() // Types excluded from export diff --git a/code/modules/cargo/exports/gear.dm b/code/modules/cargo/exports/gear.dm index 8dba7f69da..646e1c6e47 100644 --- a/code/modules/cargo/exports/gear.dm +++ b/code/modules/cargo/exports/gear.dm @@ -1,5 +1,6 @@ /datum/export/gear include_subtypes = FALSE + k_elasticity = 0 //We always want clothing/gear //blanket /datum/export/gear/hat diff --git a/code/modules/cargo/exports/large_objects.dm b/code/modules/cargo/exports/large_objects.dm index b7bdcb1f59..c7a5e59046 100644 --- a/code/modules/cargo/exports/large_objects.dm +++ b/code/modules/cargo/exports/large_objects.dm @@ -111,7 +111,7 @@ include_subtypes = FALSE /datum/export/large/am_control_unit - cost = 4000 + cost = 2000 unit_name = "antimatter control unit" export_types = list(/obj/machinery/power/am_control_unit) diff --git a/code/modules/cargo/exports/organs_robotics.dm b/code/modules/cargo/exports/organs_robotics.dm index 7a77568cc7..a6c5ee93ca 100644 --- a/code/modules/cargo/exports/organs_robotics.dm +++ b/code/modules/cargo/exports/organs_robotics.dm @@ -2,15 +2,14 @@ /datum/export/robotics include_subtypes = FALSE - k_elasticity = 0 //ALWAYS worth selling upgrades + k_elasticity = 1/50 /datum/export/implant include_subtypes = FALSE - k_elasticity = 0 //ALWAYS worth selling upgrades + k_elasticity = 1/50 /datum/export/organs include_subtypes = TRUE - k_elasticity = 0 //ALWAYS worth selling orgains /datum/export/implant/autodoc cost = 150 @@ -60,11 +59,6 @@ unit_name = "thrusters set implant" export_types = list(/obj/item/organ/cyberimp/chest/thrusters) -/datum/export/implant/thrusters - cost = 150 - unit_name = "thrusters set implant" - export_types = list(/obj/item/organ/cyberimp/chest/thrusters) - /datum/export/implant/arm cost = 200 unit_name = "arm set implant" diff --git a/code/modules/cargo/exports/parts.dm b/code/modules/cargo/exports/parts.dm index 660d79cae4..da3c0cf31d 100644 --- a/code/modules/cargo/exports/parts.dm +++ b/code/modules/cargo/exports/parts.dm @@ -110,7 +110,7 @@ include_subtypes = FALSE /datum/export/glasswork_lens - cost = 1800 + cost = 1600 unit_name = "small glass lens" export_types = list(/obj/item/glasswork/glass_base/lens) @@ -133,13 +133,13 @@ include_subtypes = FALSE /datum/export/glasswork_teaplate - cost = 1200 + cost = 1000 unit_name = "tea gear" export_types = list(/obj/item/tea_plate) include_subtypes = FALSE /datum/export/glasswork_teacup - cost = 1800 + cost = 1600 unit_name = "tea gear" export_types = list(/obj/item/tea_cup) include_subtypes = FALSE diff --git a/code/modules/cargo/exports/sheets.dm b/code/modules/cargo/exports/sheets.dm index be0d2d6bee..120bfbe5e4 100644 --- a/code/modules/cargo/exports/sheets.dm +++ b/code/modules/cargo/exports/sheets.dm @@ -120,12 +120,6 @@ message = "of cloth" export_types = list(/obj/item/stack/sheet/cloth) -/datum/export/stack/silk - cost = 200 //The new plasma - unit_name = "sheets" - message = "of silk" - export_types = list(/obj/item/stack/sheet/silk) - /datum/export/stack/duracloth cost = 40 unit_name = "sheets" diff --git a/code/modules/cargo/exports/tools.dm b/code/modules/cargo/exports/tools.dm index a68d7238b5..a889f0ed13 100644 --- a/code/modules/cargo/exports/tools.dm +++ b/code/modules/cargo/exports/tools.dm @@ -1,4 +1,7 @@ -/datum/export/toolbox +/datum/export/tool + k_elasticity = 1/500 //Tool selling almost allways fine a target + +/datum/export/tool/toolbox cost = 6 unit_name = "toolbox" export_types = list(/obj/item/storage/toolbox) @@ -29,93 +32,93 @@ // Lights/Eletronic -/datum/export/lights +/datum/export/tool/lights cost = 10 unit_name = "light fixer" export_types = list(/obj/item/wallframe/light_fixture) include_subtypes = TRUE -/datum/export/apc_board +/datum/export/tool/apc_board cost = 5 unit_name = "apc electronics" export_types = list(/obj/item/electronics/apc) include_subtypes = TRUE -/datum/export/apc_frame +/datum/export/tool/apc_frame cost = 3 unit_name = "apc frame" export_types = list(/obj/item/wallframe/apc) include_subtypes = TRUE -/datum/export/floodlights +/datum/export/tool/floodlights cost = 15 unit_name = "floodlight fixer" export_types = list(/obj/structure/floodlight_frame) include_subtypes = TRUE -/datum/export/bolbstubes +/datum/export/tool/bolbstubes cost = 1 //Time unit_name = "light replacement" export_types = list(/obj/item/light/tube, /obj/item/light/bulb) -/datum/export/lightreplacer +/datum/export/tool/lightreplacer cost = 20 unit_name = "lightreplacer" export_types = list(/obj/item/lightreplacer) // Basic tools -/datum/export/basicmining +/datum/export/tool/basicmining cost = 30 unit_name = "basic mining tool" export_types = list(/obj/item/pickaxe, /obj/item/pickaxe/mini, /obj/item/shovel, /obj/item/resonator) include_subtypes = FALSE -/datum/export/upgradedmining +/datum/export/tool/upgradedmining cost = 80 unit_name = "mining tool" export_types = list(/obj/item/pickaxe/silver, /obj/item/pickaxe/drill, /obj/item/gun/energy/plasmacutter, /obj/item/resonator/upgraded) include_subtypes = FALSE -/datum/export/advdmining +/datum/export/tool/advdmining cost = 150 unit_name = "advanced mining tool" export_types = list(/obj/item/pickaxe/diamond, /obj/item/pickaxe/drill/diamonddrill, /obj/item/pickaxe/drill/jackhammer, /obj/item/gun/energy/plasmacutter/adv) include_subtypes = FALSE -/datum/export/screwdriver +/datum/export/tool/screwdriver cost = 2 unit_name = "screwdriver" export_types = list(/obj/item/screwdriver) include_subtypes = FALSE -/datum/export/wrench +/datum/export/tool/wrench cost = 2 unit_name = "wrench" export_types = list(/obj/item/wrench) -/datum/export/crowbar +/datum/export/tool/crowbar cost = 2 unit_name = "crowbar" export_types = list(/obj/item/crowbar) -/datum/export/wirecutters +/datum/export/tool/wirecutters cost = 2 unit_name = "pair" message = "of wirecutters" export_types = list(/obj/item/wirecutters) -/datum/export/weldingtool +/datum/export/tool/weldingtool cost = 5 unit_name = "welding tool" export_types = list(/obj/item/weldingtool) include_subtypes = FALSE -/datum/export/weldingtool/emergency +/datum/export/tool/weldingtool/emergency cost = 2 unit_name = "emergency welding tool" export_types = list(/obj/item/weldingtool/mini) -/datum/export/weldingtool/industrial +/datum/export/tool/weldingtool/industrial cost = 10 unit_name = "industrial welding tool" export_types = list(/obj/item/weldingtool/largetank, /obj/item/weldingtool/hugetank) @@ -131,23 +134,23 @@ unit_name = "pocket fire extinguisher" export_types = list(/obj/item/extinguisher/mini) -/datum/export/flashlight +/datum/export/tool/flashlight cost = 3 unit_name = "flashlight" export_types = list(/obj/item/flashlight) include_subtypes = FALSE -/datum/export/flashlight/flare +/datum/export/tool/flashlight/flare cost = 2 unit_name = "flare" export_types = list(/obj/item/flashlight/flare) -/datum/export/flashlight/seclite +/datum/export/tool/flashlight/seclite cost = 5 unit_name = "seclite" export_types = list(/obj/item/flashlight/seclite) -/datum/export/analyzer +/datum/export/tool/analyzer cost = 5 unit_name = "analyzer" export_types = list(/obj/item/analyzer) @@ -163,32 +166,32 @@ export_types = list(/obj/item/radio) exclude_types = list(/obj/item/radio/mech) -/datum/export/rcd +/datum/export/tool/rcd cost = 100 unit_name = "rapid construction device" export_types = list(/obj/item/construction/rcd) -/datum/export/rcd_ammo +/datum/export/tool/rcd_ammo cost = 60 unit_name = "compressed matter cardridge" export_types = list(/obj/item/rcd_ammo) -/datum/export/rpd +/datum/export/tool/rpd cost = 100 unit_name = "rapid piping device" export_types = list(/obj/item/pipe_dispenser) -/datum/export/rld +/datum/export/tool/rld cost = 150 unit_name = "rapid light device" export_types = list(/obj/item/construction/rld) -/datum/export/rped +/datum/export/tool/rped cost = 100 unit_name = "rapid part exchange device" export_types = list(/obj/item/storage/part_replacer) -/datum/export/bsrped +/datum/export/tool/bsrped cost = 200 unit_name = "blue space part exchange device" export_types = list(/obj/item/storage/part_replacer/bluespace) diff --git a/code/modules/cargo/expressconsole.dm b/code/modules/cargo/expressconsole.dm index a65d8cad40..9fe427c45a 100644 --- a/code/modules/cargo/expressconsole.dm +++ b/code/modules/cargo/expressconsole.dm @@ -96,17 +96,19 @@ /obj/machinery/computer/cargo/express/ui_data(mob/user) var/canBeacon = beacon && (isturf(beacon.loc) || ismob(beacon.loc))//is the beacon in a valid location? var/list/data = list() + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + if(D) + data["points"] = D.account_balance data["locked"] = locked//swipe an ID to unlock data["siliconUser"] = hasSiliconAccessInArea(user) data["beaconzone"] = beacon ? get_area(beacon) : ""//where is the beacon located? outputs in the tgui data["usingBeacon"] = usingBeacon //is the mode set to deliver to the beacon or the cargobay? data["canBeacon"] = !usingBeacon || canBeacon //is the mode set to beacon delivery, and is the beacon in a valid location? - data["canBuyBeacon"] = cooldown <= 0 && SSshuttle.points >= BEACON_COST + data["canBuyBeacon"] = cooldown <= 0 && D.account_balance >= BEACON_COST data["beaconError"] = usingBeacon && !canBeacon ? "(BEACON ERROR)" : ""//changes button text to include an error alert if necessary data["hasBeacon"] = beacon != null//is there a linked beacon? data["beaconName"] = beacon ? beacon.name : "No Beacon Found" data["printMsg"] = cooldown > 0 ? "Print Beacon for [BEACON_COST] credits ([cooldown])" : "Print Beacon for [BEACON_COST] credits"//buttontext for printing beacons - data["points"] = SSshuttle.points data["supplies"] = list() message = "Sales are near-instantaneous - please choose carefully." if(SSshuttle.supplyBlocked) @@ -127,6 +129,9 @@ return data /obj/machinery/computer/cargo/express/ui_act(action, params, datum/tgui/ui) + if(!allowed(usr)) + to_chat(usr, "Access denied.") + return switch(action) if("LZCargo") usingBeacon = FALSE @@ -137,13 +142,14 @@ if (beacon) beacon.update_status(SP_READY) //turns on the beacon's ready light if("printBeacon") - if (SSshuttle.points >= BEACON_COST) - cooldown = 10//a ~ten second cooldown for printing beacons to prevent spam - var/obj/item/supplypod_beacon/C = new /obj/item/supplypod_beacon(drop_location()) - C.link_console(src, usr)//rather than in beacon's Initialize(), we can assign the computer to the beacon by reusing this proc) - printed_beacons++//printed_beacons starts at 0, so the first one out will be called beacon # 1 - beacon.name = "Supply Pod Beacon #[printed_beacons]" - SSshuttle.points -= BEACON_COST + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + if(D) + if(D.adjust_money(-BEACON_COST)) + cooldown = 10//a ~ten second cooldown for printing beacons to prevent spam + var/obj/item/supplypod_beacon/C = new /obj/item/supplypod_beacon(drop_location()) + C.link_console(src, usr)//rather than in beacon's Initialize(), we can assign the computer to the beacon by reusing this proc) + printed_beacons++//printed_beacons starts at 0, so the first one out will be called beacon # 1 + beacon.name = "Supply Pod Beacon #[printed_beacons]" if("add")//Generate Supply Order first var/id = text2path(params["id"]) @@ -163,8 +169,12 @@ var/reason = "" var/list/empty_turfs var/datum/supply_order/SO = new(pack, name, rank, ckey, reason) + var/points_to_check + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + if(D) + points_to_check = D.account_balance if(!(obj_flags & EMAGGED)) - if(SO.pack.cost <= SSshuttle.points) + if(SO.pack.cost <= points_to_check) var/LZ if (istype(beacon) && usingBeacon)//prioritize beacons over landing in cargobay LZ = get_turf(beacon) @@ -181,14 +191,14 @@ CHECK_TICK if(empty_turfs && empty_turfs.len) LZ = pick(empty_turfs) - if (SO.pack.cost <= SSshuttle.points && LZ)//we need to call the cost check again because of the CHECK_TICK call - SSshuttle.points -= SO.pack.cost + if (SO.pack.cost <= points_to_check && LZ)//we need to call the cost check again because of the CHECK_TICK call + D.adjust_money(-SO.pack.cost) SSblackbox.record_feedback("nested tally", "cargo_imports", 1, list("[SO.pack.cost]", "[SO.pack.name]")) new /obj/effect/abstract/DPtarget(LZ, podType, SO) . = TRUE update_icon() else - if(SO.pack.cost * (0.72*MAX_EMAG_ROCKETS) <= SSshuttle.points) // bulk discount :^) + if(SO.pack.cost * (0.72*MAX_EMAG_ROCKETS) <= points_to_check) // bulk discount :^) landingzone = GLOB.areas_by_type[pick(GLOB.the_station_areas)] //override default landing zone for(var/turf/open/floor/T in landingzone.contents) if(is_blocked_turf(T)) @@ -196,7 +206,7 @@ LAZYADD(empty_turfs, T) CHECK_TICK if(empty_turfs && empty_turfs.len) - SSshuttle.points -= SO.pack.cost * (0.72*MAX_EMAG_ROCKETS) + D.adjust_money(-(SO.pack.cost * (0.72*MAX_EMAG_ROCKETS))) SSblackbox.record_feedback("nested tally", "cargo_imports", MAX_EMAG_ROCKETS, list("[SO.pack.cost * 0.72]", "[SO.pack.name]")) SO.generateRequisition(get_turf(src)) for(var/i in 1 to MAX_EMAG_ROCKETS) diff --git a/code/modules/cargo/gondolapod.dm b/code/modules/cargo/gondolapod.dm index 1b4ebd6c1a..be2db06346 100644 --- a/code/modules/cargo/gondolapod.dm +++ b/code/modules/cargo/gondolapod.dm @@ -2,9 +2,12 @@ name = "gondola" real_name = "gondola" desc = "The silent walker. This one seems to be part of a delivery agency." - response_help = "pets" - response_disarm = "bops" - response_harm = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "bops" + response_disarm_simple = "bop" + response_harm_continuous = "kicks" + response_harm_simple = "kick" faction = list("gondola") turns_per_move = 10 icon = 'icons/mob/gondolapod.dmi' diff --git a/code/modules/cargo/order.dm b/code/modules/cargo/order.dm index 13e223bca3..3d1caf6ba6 100644 --- a/code/modules/cargo/order.dm +++ b/code/modules/cargo/order.dm @@ -28,14 +28,16 @@ var/orderer_ckey var/reason var/datum/supply_pack/pack + var/datum/bank_account/paying_account -/datum/supply_order/New(datum/supply_pack/pack, orderer, orderer_rank, orderer_ckey, reason) +/datum/supply_order/New(datum/supply_pack/pack, orderer, orderer_rank, orderer_ckey, reason, paying_account) id = SSshuttle.ordernum++ src.pack = pack src.orderer = orderer src.orderer_rank = orderer_rank src.orderer_ckey = orderer_ckey src.reason = reason + src.paying_account = paying_account /datum/supply_order/proc/generateRequisition(turf/T) var/obj/item/paper/P = new(T) @@ -47,6 +49,8 @@ P.info += "Item: [pack.name]
" P.info += "Access Restrictions: [get_access_desc(pack.access)]
" P.info += "Requested by: [orderer]
" + if(paying_account) + P.info += "Paid by: [paying_account.account_holder]
" P.info += "Rank: [orderer_rank]
" P.info += "Comment: [reason]
" @@ -61,6 +65,9 @@ P.name = "shipping manifest - #[id] ([pack.name])" P.info += "

[command_name()] Shipping Manifest

" P.info += "
" + if(paying_account) + P.info += "Direct purchase from [paying_account.account_holder]
" + P.name += " - Purchased by [paying_account.account_holder]" P.info += "Order #[id]
" P.info += "Destination: [station_name]
" P.info += "Item: [pack.name]
" @@ -81,7 +88,7 @@ return P /datum/supply_order/proc/generate(atom/A) - var/obj/structure/closet/crate/C = pack.generate(A) + var/obj/structure/closet/crate/C = pack.generate(A, paying_account) var/obj/item/paper/fluff/jobs/cargo/manifest/M = generateManifest(C) if(M.errors & MANIFEST_ERROR_ITEM) diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm index 07a75bbfaf..f82e16ad5c 100644 --- a/code/modules/cargo/packs.dm +++ b/code/modules/cargo/packs.dm @@ -15,17 +15,22 @@ var/special_enabled = FALSE var/DropPodOnly = FALSE //only usable by the Bluespace Drop Pod via the express cargo console var/admin_spawned = FALSE //Can only an admin spawn this crate? + var/can_private_buy = TRUE //Can it be purchased privately by each crewmember? -/datum/supply_pack/proc/generate(atom/A) - var/obj/structure/closet/crate/C = new crate_type(A) - C.name = crate_name +/datum/supply_pack/proc/generate(atom/A, datum/bank_account/paying_account) + var/obj/structure/closet/crate/C + if(paying_account) + C = new /obj/structure/closet/crate/secure/owned(A, paying_account) + C.name = "[crate_name] - Purchased by [paying_account.account_holder]" + else + C = new crate_type(A) + C.name = crate_name if(access) C.req_access = list(access) if(access_any) C.req_one_access = access_any fill(C) - return C /datum/supply_pack/proc/fill(obj/structure/closet/crate/C) diff --git a/code/modules/cargo/packs/armory.dm b/code/modules/cargo/packs/armory.dm index 501b1426ae..3a3357cc42 100644 --- a/code/modules/cargo/packs/armory.dm +++ b/code/modules/cargo/packs/armory.dm @@ -10,6 +10,7 @@ group = "Armory" access = ACCESS_ARMORY crate_type = /obj/structure/closet/crate/secure/weapon + can_private_buy = FALSE /datum/supply_pack/security/armory/bulletarmor name = "Bulletproof Armor Crate" @@ -170,8 +171,7 @@ cost = 7500 contraband = TRUE contains = list(/obj/item/reagent_containers/food/snacks/rationpack, - /obj/item/ammo_box/a762, - /obj/item/storage/toolbox/ammo, + /obj/item/ammo_box/magazine/m10mm/rifle, /obj/item/clothing/suit/armor/vest/russian, /obj/item/clothing/head/helmet/rus_helmet, /obj/item/clothing/shoes/russian, @@ -181,7 +181,7 @@ /obj/item/clothing/mask/russian_balaclava, /obj/item/clothing/head/helmet/rus_ushanka, /obj/item/clothing/suit/armor/vest/russian_coat, - /obj/item/gun/ballistic/shotgun/boltaction) + /obj/item/gun/ballistic/automatic/surplus) crate_name = "surplus military crate" /datum/supply_pack/security/armory/russian/fill(obj/structure/closet/crate/C) @@ -215,7 +215,7 @@ /datum/supply_pack/security/armory/wt550ammo name = "WT-550 Semi-Auto SMG Ammo Crate" - desc = "Contains four 20-round magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open." + desc = "Contains four 32-round magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open." cost = 1750 contains = list(/obj/item/ammo_box/magazine/wt550m9, /obj/item/ammo_box/magazine/wt550m9, @@ -225,7 +225,7 @@ /datum/supply_pack/security/armory/wt550ammo_nonlethal // Takes around 12 shots to stamcrit someone name = "WT-550 Semi-Auto SMG Non-Lethal Ammo Crate" - desc = "Contains four 20-round magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open." + desc = "Contains four 32-round magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open." cost = 1000 contains = list(/obj/item/ammo_box/magazine/wt550m9/wtrubber, /obj/item/ammo_box/magazine/wt550m9/wtrubber, diff --git a/code/modules/cargo/packs/engine.dm b/code/modules/cargo/packs/engine.dm index 89775c07ee..499881a110 100644 --- a/code/modules/cargo/packs/engine.dm +++ b/code/modules/cargo/packs/engine.dm @@ -148,7 +148,7 @@ crate_name = "supermatter shard crate" crate_type = /obj/structure/closet/crate/secure/engineering dangerous = TRUE - + /datum/supply_pack/engine/tesla_coils name = "Tesla Coil Crate" desc = "Whether it's high-voltage executions, creating research points, or just plain old power generation: This pack of four Tesla coils can do it all!" diff --git a/code/modules/cargo/packs/materials.dm b/code/modules/cargo/packs/materials.dm index 1ce3a6b084..771f7ce222 100644 --- a/code/modules/cargo/packs/materials.dm +++ b/code/modules/cargo/packs/materials.dm @@ -81,32 +81,6 @@ contains = list(/obj/item/stack/sheet/mineral/wood/fifty) crate_name = "wood planks crate" -/datum/supply_pack/materials/rawcotton - name = "Raw Cotton Crate" - desc = "Plushies have been on the down in the market, and now due to a flood of raw cotton the price of it is so cheap, its a steal! Contains 40 raw cotton sheets." - cost = 800 // 100 net cost, 20 x 20 = 400. 300 profit if turned into cloth sheets or more if turned to silk then 10 x 200 = 2000 - contains = list(/obj/item/stack/sheet/cotton/thirty, - /obj/item/stack/sheet/cotton/ten - ) - crate_name = "cotton crate" - crate_type = /obj/structure/closet/crate/hydroponics - -/datum/supply_pack/materials/rawcottonbulk - name = "Raw Cotton Crate (Bulk)" - desc = "We have so much of this stuff we need to get rid of it in -bulk- now. This crate contains 240 raw cotton sheets." - cost = 1300 // 600 net cost 20 x 120 = 2400 profit if turned into cloth sheets or if turned into silk 200 x 60 = 12000 - contains = list(/obj/item/stack/sheet/cotton/thirty, - /obj/item/stack/sheet/cotton/thirty, - /obj/item/stack/sheet/cotton/thirty, - /obj/item/stack/sheet/cotton/thirty, - /obj/item/stack/sheet/cotton/thirty, - /obj/item/stack/sheet/cotton/thirty, - /obj/item/stack/sheet/cotton/thirty, - /obj/item/stack/sheet/cotton/thirty, - ) - crate_name = "bulk cotton crate" - crate_type = /obj/structure/closet/crate/hydroponics - /datum/supply_pack/materials/rcdammo name = "Spare RCD ammo" desc = "This crate contains sixteen RCD compressed matter packs, to help with any holes or projects people might be working on." diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm index 5d02bbe60f..ab188f235b 100644 --- a/code/modules/cargo/packs/medical.dm +++ b/code/modules/cargo/packs/medical.dm @@ -252,6 +252,7 @@ crate_name = "virus crate" crate_type = /obj/structure/closet/crate/secure/plasma dangerous = TRUE + can_private_buy = FALSE /datum/supply_pack/medical/anitvirus name = "Virus Containment Crate" @@ -271,4 +272,4 @@ /obj/item/storage/box/syringes, /obj/item/storage/box/beakers) crate_name = "virus containment unit crate" - crate_type = /obj/structure/closet/crate/secure/plasma \ No newline at end of file + crate_type = /obj/structure/closet/crate/secure/plasma diff --git a/code/modules/cargo/packs/organic.dm b/code/modules/cargo/packs/organic.dm index 22cb518926..249faae33d 100644 --- a/code/modules/cargo/packs/organic.dm +++ b/code/modules/cargo/packs/organic.dm @@ -370,22 +370,6 @@ /////////////////////////////////// Misc ///////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -/datum/supply_pack/organic/hunting - name = "Hunting Gear" - desc = "Even in space, we can find prey to hunt, this crate contains everthing a fine hunter needs to have a sporting time. This crate needs armory access to open. A true huntter only needs a fine bottle of cognac, a nice coat, some good o' cigars, and of cource a hunting shotgun. " - cost = 3500 - contraband = TRUE - contains = list(/obj/item/clothing/head/flatcap, - /obj/item/clothing/suit/hooded/wintercoat/captain, - /obj/item/reagent_containers/food/drinks/bottle/cognac, - /obj/item/storage/fancy/cigarettes/cigars/havana, - /obj/item/clothing/gloves/color/white, - /obj/item/clothing/under/rank/civilian/curator, - /obj/item/gun/ballistic/shotgun/lethal) - access = ACCESS_ARMORY - crate_name = "sporting crate" - crate_type = /obj/structure/closet/crate/secure // Would have liked a wooden crate but access >:( - /datum/supply_pack/organic/party name = "Party Equipment" desc = "Celebrate both life and death on the station with Nanotrasen's Party Essentials(tm)! Contains seven colored glowsticks, four beers, two ales, a drinking shaker, and a bottle of patron & goldschlager!" diff --git a/code/modules/cargo/packs/science.dm b/code/modules/cargo/packs/science.dm index a3548a5eb6..fd6fee362d 100644 --- a/code/modules/cargo/packs/science.dm +++ b/code/modules/cargo/packs/science.dm @@ -10,24 +10,14 @@ group = "Science" crate_type = /obj/structure/closet/crate/science -/* For later -/datum/supply_pack/science/monkey +/datum/supply_pack/science/ape //Ape out! name = "Ape Cube Crate" desc = "Pss what a new test subject with supper strangth, speed, and love for bananas all at the same time? Say no more... Contains a single ape cube. Dont add water!" contraband = TRUE cost = 2500 - contains = list (/obj/item/reagent_containers/food/snacks/monkeycube/ape) + contains = list (/obj/item/reagent_containers/food/snacks/cube/ape) crate_name = "ape cube crate" -*/ - -/datum/supply_pack/science/aliens - name = "Advanced Alien Alloy Crate Crate" - desc = "Hello brothers from the stars!!! Our fellow brethren have made contact at long last and gave us gifts man! They really did build the prymi- Connection Error- Bro we’ll send you a sheet of advanced alien alloy." - cost = 15000 - DropPodOnly = TRUE - contraband = TRUE - contains = list(/obj/item/stack/sheet/mineral/abductor) - crate_name = "alien bro alloy crate" + can_private_buy = FALSE /datum/supply_pack/science/beakers name = "Chemistry Beakers Crate" diff --git a/code/modules/cargo/packs/security.dm b/code/modules/cargo/packs/security.dm index ee750b8df7..a48874e974 100644 --- a/code/modules/cargo/packs/security.dm +++ b/code/modules/cargo/packs/security.dm @@ -10,6 +10,7 @@ group = "Security" access = ACCESS_SECURITY crate_type = /obj/structure/closet/crate/secure/gear + can_private_buy = FALSE /datum/supply_pack/security/ammo name = "Ammo Crate - General Purpose" @@ -57,6 +58,7 @@ /obj/item/toy/crayon/white, /obj/item/clothing/head/fedora/det_hat) crate_name = "forensics crate" + can_private_buy = TRUE /datum/supply_pack/security/helmets name = "Helmets Crate" @@ -99,11 +101,11 @@ crate_type = /obj/structure/closet/crate/internals /datum/supply_pack/security/russianmosin - name = "Russian Minutemen Gear" - desc = "An old russian Minutemen crate, comes with a full russian outfit, a mosin and a stripper clip." + name = "Russian Partisan Gear" + desc = "An old russian partisan equipment crate, comes with a full russian outfit, a loaded surplus rifle and a second magazine." contraband = TRUE access = FALSE - cost = 6500 // + cost = 6500 contains = list(/obj/item/clothing/suit/armor/navyblue/russian, /obj/item/clothing/shoes/combat, /obj/item/clothing/head/ushanka, @@ -111,8 +113,8 @@ /obj/item/clothing/head/helmet/alt, /obj/item/clothing/gloves/tackler/combat/insulated, /obj/item/clothing/mask/gas, - /obj/item/gun/ballistic/shotgun/boltaction, - /obj/item/ammo_box/a762) + /obj/item/ammo_box/magazine/m10mm/rifle, + /obj/item/gun/ballistic/automatic/surplus) crate_name = "surplus russian gear" crate_type = /obj/structure/closet/crate/internals @@ -134,6 +136,7 @@ /obj/item/grenade/barrier) cost = 2000 crate_name = "security barriers crate" + can_private_buy = TRUE /datum/supply_pack/security/securityclothes name = "Security Clothing Crate" @@ -152,6 +155,7 @@ /obj/item/clothing/suit/armor/hos/navyblue, /obj/item/clothing/head/beret/sec/navyhos) crate_name = "security clothing crate" + can_private_buy = TRUE /datum/supply_pack/security/supplies name = "Security Supplies Crate" @@ -179,6 +183,7 @@ contains = list(/obj/item/clothing/head/helmet/justice, /obj/item/clothing/mask/gas/sechailer) crate_name = "security clothing crate" + can_private_buy = TRUE /datum/supply_pack/security/baton name = "Stun Batons Crate" @@ -207,3 +212,19 @@ /obj/item/storage/box/wall_flash, /obj/item/storage/box/wall_flash) crate_name = "wall-mounted flash crate" + +/datum/supply_pack/security/hunting + name = "Hunting Gear" + desc = "Even in space, we can find prey to hunt, this crate contains everthing a fine hunter needs to have a sporting time. This crate needs armory access to open. A true huntter only needs a fine bottle of cognac, a nice coat, some good o' cigars, and of cource a hunting shotgun. " + cost = 3500 + contraband = TRUE + contains = list(/obj/item/clothing/head/flatcap, + /obj/item/clothing/suit/hooded/wintercoat/captain, + /obj/item/reagent_containers/food/drinks/bottle/cognac, + /obj/item/storage/fancy/cigarettes/cigars/havana, + /obj/item/clothing/gloves/color/white, + /obj/item/clothing/under/rank/civilian/curator, + /obj/item/gun/ballistic/shotgun/lethal) + access = ACCESS_ARMORY + crate_name = "sporting crate" + crate_type = /obj/structure/closet/crate/secure // Would have liked a wooden crate but access >:( diff --git a/code/modules/cargo/packs/vending.dm b/code/modules/cargo/packs/vending.dm index 344d19f6c9..810cfd8d6e 100644 --- a/code/modules/cargo/packs/vending.dm +++ b/code/modules/cargo/packs/vending.dm @@ -99,6 +99,7 @@ contains = list(/obj/machinery/vending/security) crate_name = "SecTech supply crate" crate_type = /obj/structure/closet/crate/secure/gear + can_private_buy = FALSE /datum/supply_pack/vending/snack name = "Snack Supply Crate" diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index f865cfddbb..1659a4ff37 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -80,10 +80,26 @@ var/list/char_render_holders //Should only be a key-value list of north/south/east/west = obj/screen. + /// Keys currently held + var/list/keys_held = list() + /// These next two vars are to apply movement for keypresses and releases made while move delayed. + /// Because discarding that input makes the game less responsive. + /// On next move, add this dir to the move that would otherwise be done + var/next_move_dir_add + /// On next move, subtract this dir from the move that would otherwise be done + var/next_move_dir_sub + /// Amount of keydowns in the last keysend checking interval var/client_keysend_amount = 0 + /// World tick time where client_keysend_amount will reset var/next_keysend_reset = 0 + /// World tick time where keysend_tripped will reset back to false var/next_keysend_trip_reset = 0 + /// When set to true, user will be autokicked if they trip the keysends in a second limit again var/keysend_tripped = FALSE + /// custom movement keys for this client + var/list/movement_keys = list() /// Messages currently seen by this client var/list/seen_messages + ///When was the last time we warned them about not cryoing without an ahelp, set to -5 minutes so that rounstart cryo still warns + var/cryo_warned = -5 MINUTES \ No newline at end of file diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 989ccaf450..ce7ef441c4 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -265,6 +265,9 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) else prefs = new /datum/preferences(src) GLOB.preferences_datums[ckey] = prefs + if(SSinput.initialized) + set_macros() + update_movement_keys(prefs) prefs.last_ip = address //these are gonna be used for banning prefs.last_id = computer_id //these are gonna be used for banning @@ -328,9 +331,6 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) qdel(src) return - if(SSinput.initialized) - set_macros() - chatOutput.start() // Starts the chat if(alert_mob_dupe_login) @@ -789,7 +789,9 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) log_game("[key_name(src)] is using the middle click aimbot exploit") message_admins("[ADMIN_LOOKUPFLW(src)] [ADMIN_KICK(usr)] is using the middle click aimbot exploit") add_system_note("aimbot", "Is using the middle click aimbot exploit") - + log_click(object, location, control, params, src, "lockout (spam - minute ab c [ab] s [middragtime])") + else + log_click(object, location, control, params, src, "lockout (spam - minute)") log_game("[key_name(src)] Has hit the per-minute click limit of [mcl] clicks in a given game minute") message_admins("[ADMIN_LOOKUPFLW(src)] [ADMIN_KICK(usr)] Has hit the per-minute click limit of [mcl] clicks in a given game minute") to_chat(src, "[msg]") @@ -809,8 +811,12 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) return if(ab) //Citadel edit, things with stuff. + log_click(object, location, control, params, src, "dropped (ab c [ab] s [middragtime])") return + if(prefs.log_clicks) + log_click(object, location, control, params, src) + if (prefs.hotkeys) // If hotkey mode is enabled, then clicking the map will automatically // unfocus the text bar. This removes the red color from the text bar @@ -892,6 +898,23 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) y = clamp(y+change, min,max) change_view("[x]x[y]") +/client/proc/update_movement_keys(datum/preferences/direct_prefs) + var/datum/preferences/D = prefs || direct_prefs + if(!D?.key_bindings) + return + movement_keys = list() + for(var/key in D.key_bindings) + for(var/kb_name in D.key_bindings[key]) + switch(kb_name) + if("North") + movement_keys[key] = NORTH + if("East") + movement_keys[key] = EAST + if("West") + movement_keys[key] = WEST + if("South") + movement_keys[key] = SOUTH + /client/proc/change_view(new_size) if (isnull(new_size)) CRASH("change_view called without argument.") @@ -902,23 +925,27 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) new_size = "15x15" //END OF CIT CHANGES + var/list/old_view = getviewsize(view) view = new_size - apply_clickcatcher() + var/list/actualview = getviewsize(view) + apply_clickcatcher(actualview) mob.reload_fullscreen() if (isliving(mob)) var/mob/living/M = mob M.update_damage_hud() if (prefs.auto_fit_viewport) fit_viewport() + SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_CHANGE_VIEW, src, old_view, actualview) /client/proc/generate_clickcatcher() if(!void) void = new() screen += void -/client/proc/apply_clickcatcher() +/client/proc/apply_clickcatcher(list/actualview) generate_clickcatcher() - var/list/actualview = getviewsize(view) + if(!actualview) + actualview = getviewsize(view) void.UpdateGreed(actualview[1],actualview[2]) /client/proc/AnnouncePR(announcement) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index bb3a435258..040b56f124 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -1,11 +1,6 @@ - /* CAUTION! CAUTION! CAUTION! CAUTION! CAUTION! *\ - | THIS FILE CONTAINS HOOKS FOR FOR | - | CHANGES SPECIFIC TO CITADEL. IF | - | YOU'RE FIXING A MERGE CONFLICT | - | HERE, PLEASE ASK FOR REVIEW FROM | - | ANOTHER MAINTAINER TO ENSURE YOU | - | DON'T INTRODUCE REGRESSIONS. | - \* */ +#define DEFAULT_SLOT_AMT 2 +#define HANDS_SLOT_AMT 2 +#define BACKPACK_SLOT_AMT 4 GLOBAL_LIST_EMPTY(preferences_datums) @@ -20,6 +15,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/muted = 0 var/last_ip var/last_id + var/log_clicks = FALSE var/icon/custom_holoform_icon var/list/cached_holoform_icons @@ -51,6 +47,11 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/chat_on_map = TRUE var/max_chat_length = CHAT_MESSAGE_MAX_LENGTH var/see_chat_non_mob = TRUE + + /// Custom Keybindings + var/list/key_bindings = list() + + var/tgui_fancy = TRUE var/tgui_lock = TRUE var/windowflashing = TRUE @@ -153,6 +154,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) "ipc_screen" = "Sunburst", "ipc_antenna" = "None", "flavor_text" = "", + "ooc_notes" = "", "meat_type" = "Mammalian", "body_model" = MALE, "body_size" = RESIZE_DEFAULT_SIZE @@ -188,9 +190,6 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/uplink_spawn_loc = UPLINK_PDA - var/sprint_spacebar = FALSE - var/sprint_toggle = FALSE - var/hud_toggle_flash = TRUE var/hud_toggle_color = "#ffffff" @@ -203,6 +202,10 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/vore_flags = 0 var/list/belly_prefs = list() var/vore_taste = "nothing in particular" + var/toggleeatingnoise = TRUE + var/toggledigestionnoise = TRUE + var/hound_sleeper = TRUE + var/cit_toggles = TOGGLES_CITADEL //backgrounds var/mutable_appearance/character_background @@ -213,6 +216,19 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/no_tetris_storage = FALSE + ///loadout stuff + var/gear_points = 10 + var/list/gear_categories + var/list/chosen_gear = list() + var/gear_tab + + var/screenshake = 100 + var/damagescreenshake = 2 + var/arousable = TRUE + var/widescreenpref = TRUE + var/autostand = TRUE + var/auto_ooc = FALSE + /datum/preferences/New(client/C) parent = C @@ -232,6 +248,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) return //we couldn't load character data so just randomize the character appearance + name random_character() //let's create a random character then - rather than a fat, bald and naked man. + key_bindings = deepCopyList(GLOB.hotkey_keybinding_list_by_key) // give them default keybinds and update their movement keys + C?.update_movement_keys(src) real_name = pref_species.random_name(gender,1) if(!loaded_preferences_successfully) save_preferences() @@ -253,6 +271,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Loadout" dat += "Game Preferences" dat += "Content Preferences" + dat += "Keybindings" if(!path) dat += "
Please create an account to save your preferences
" @@ -348,6 +367,16 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "[features["flavor_text"]]" else dat += "[TextPreview(features["flavor_text"])]...
" + dat += "

OOC notes

" + dat += "Set OOC notes
" + var/ooc_notes_len = length(features["ooc_notes"]) + if(ooc_notes_len <= 40) + if(!ooc_notes_len) + dat += "\[...\]" + else + dat += "[features["ooc_notes"]]" + else + dat += "[TextPreview(features["ooc_notes"])]...
" dat += "

Body

" dat += "Gender:[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]
" if(gender != NEUTER && pref_species.sexes) @@ -384,7 +413,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) mutant_colors = TRUE if (CONFIG_GET(number/body_size_min) != CONFIG_GET(number/body_size_max)) - dat += "Sprite Size:[features["body_size"]]%
" + dat += "Sprite Size:[features["body_size"]*100]%
" if((EYECOLOR in pref_species.species_traits) && !(NOEYES in pref_species.species_traits)) @@ -832,7 +861,6 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "See Runechat for non-mobs:[see_chat_non_mob ? "Enabled" : "Disabled"]
" dat += "
" dat += "Action Buttons:[(buttons_locked) ? "Locked In Place" : "Unlocked"]
" - dat += "Keybindings:[(hotkeys) ? "Hotkeys" : "Default"]
" dat += "
" dat += "PDA Color:   Change
" dat += "PDA Style:[pda_style]
" @@ -907,7 +935,12 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Ghosts of Others:[button_name]
" dat += "
" + dat += "FPS:[clientfps]
" + + dat += "Income Updates:[(chat_toggles & CHAT_BANKCARD) ? "Allowed" : "Muted"]
" + dat += "
" + dat += "Parallax (Fancy Space):" switch (parallax) if (PARALLAX_LOW) @@ -923,8 +956,6 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "
" dat += "Ambient Occlusion:[ambientocclusion ? "Enabled" : "Disabled"]
" dat += "Fit Viewport:[auto_fit_viewport ? "Auto" : "Manual"]
" - dat += "Sprint Key:[sprint_spacebar ? "Space" : "Shift"]
" - dat += "Toggle Sprint:[sprint_toggle ? "Enabled" : "Disabled"]
" dat += "HUD Button Flashes:[hud_toggle_flash ? "Enabled" : "Disabled"]
" dat += "HUD Button Flash Color:   Change
" @@ -1047,6 +1078,56 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Ass Slapping:[(cit_toggles & NO_ASS_SLAP) ? "Disallowed" : "Allowed"]
" dat += "
NameDescriptionRewardCompletionStatus
" dat += "
" + if(5) // Custom keybindings + dat += "Keybindings: [(hotkeys) ? "Hotkeys" : "Input"]
" + dat += "Keybindings mode controls how the game behaves with tab and map/input focus.
If it is on Hotkeys, the game will always attempt to force you to map focus, meaning keypresses are sent \ + directly to the map instead of the input. You will still be able to use the command bar, but you need to tab to do it every time you click on the game map.
\ + If it is on Input, the game will not force focus away from the input bar, and you can switch focus using TAB between these two modes: If the input bar is pink, that means that you are in non-hotkey mode, sending all keypresses of the normal \ + alphanumeric characters, punctuation, spacebar, backspace, enter, etc, typing keys into the input bar. If the input bar is white, you are in hotkey mode, meaning all keypresses go into the game's keybind handling system unless you \ + manually click on the input bar to shift focus there.
\ + Input mode is the closest thing to the old input system.
\ + IMPORTANT: While in input mode's non hotkey setting (tab toggled), Ctrl + KEY will send KEY to the keybind system as the key itself, not as Ctrl + KEY. This means Ctrl + T/W/A/S/D/all your familiar stuff still works, but you \ + won't be able to access any regular Ctrl binds.
" + // Create an inverted list of keybindings -> key + var/list/user_binds = list() + for (var/key in key_bindings) + for(var/kb_name in key_bindings[key]) + user_binds[kb_name] += list(key) + + var/list/kb_categories = list() + // Group keybinds by category + for (var/name in GLOB.keybindings_by_name) + var/datum/keybinding/kb = GLOB.keybindings_by_name[name] + kb_categories[kb.category] += list(kb) + + dat += "" + + for (var/category in kb_categories) + dat += "

[category]

" + for (var/i in kb_categories[category]) + var/datum/keybinding/kb = i + if(!length(user_binds[kb.name])) + dat += " Unbound" + var/list/default_keys = hotkeys ? kb.hotkey_keys : kb.classic_keys + if(LAZYLEN(default_keys)) + dat += "| Default: [default_keys.Join(", ")]" + dat += "
" + else + var/bound_key = user_binds[kb.name][1] + dat += " [bound_key]" + for(var/bound_key_index in 2 to length(user_binds[kb.name])) + bound_key = user_binds[kb.name][bound_key_index] + dat += " | [bound_key]" + if(length(user_binds[kb.name]) < MAX_KEYS_PER_KEYBIND) + dat += "| Add Secondary" + var/list/default_keys = hotkeys ? kb.classic_keys : kb.hotkey_keys + if(LAZYLEN(default_keys)) + dat += "| Default: [default_keys.Join(", ")]" + dat += "
" + + dat += "

" + dat += "\[Reset to default\]" + dat += "" dat += "
" @@ -1067,6 +1148,31 @@ GLOBAL_LIST_EMPTY(preferences_datums) #undef APPEARANCE_CATEGORY_COLUMN #undef MAX_MUTANT_ROWS +/datum/preferences/proc/CaptureKeybinding(mob/user, datum/keybinding/kb, var/old_key) + var/HTML = {" +
Keybinding: [kb.full_name]
[kb.description]

Press any key to change
Press ESC to clear
+ + "} + winshow(user, "capturekeypress", TRUE) + var/datum/browser/popup = new(user, "capturekeypress", "
Keybindings
", 350, 300) + popup.set_content(HTML) + popup.open(FALSE) + onclose(user, "capturekeypress", src) + /datum/preferences/proc/SetChoices(mob/user, limit = 17, list/splitJobs = list("Chief Engineer"), widthPerColumn = 295, height = 620) if(!SSjob) return @@ -1510,6 +1616,11 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(!isnull(msg)) features["flavor_text"] = html_decode(msg) + if("ooc_notes") + var/msg = stripped_multiline_input(usr, "Set always-visible OOC notes related to content preferences. THIS IS NOT FOR CHARACTER DESCRIPTIONS!", "OOC notes", features["ooc_notes"], MAX_FLAVOR_LEN, TRUE) + if(!isnull(msg)) + features["ooc_notes"] = html_decode(msg) + if("hair") var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference","#"+hair_color) as color|null if(new_hair) @@ -2242,10 +2353,73 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("hotkeys") hotkeys = !hotkeys - if(hotkeys) - winset(user, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED] mainwindow.macro=default") - else - winset(user, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED] mainwindow.macro=old_default") + user.client.set_macros() + + if("keybindings_capture") + var/datum/keybinding/kb = GLOB.keybindings_by_name[href_list["keybinding"]] + var/old_key = href_list["old_key"] + CaptureKeybinding(user, kb, old_key) + return + + if("keybindings_set") + var/kb_name = href_list["keybinding"] + if(!kb_name) + user << browse(null, "window=capturekeypress") + ShowChoices(user) + return + + var/clear_key = text2num(href_list["clear_key"]) + var/old_key = href_list["old_key"] + if(clear_key) + if(key_bindings[old_key]) + key_bindings[old_key] -= kb_name + if(!length(key_bindings[old_key])) + key_bindings -= old_key + user << browse(null, "window=capturekeypress") + save_preferences() + ShowChoices(user) + return + + var/new_key = uppertext(href_list["key"]) + var/AltMod = text2num(href_list["alt"]) ? "Alt" : "" + var/CtrlMod = text2num(href_list["ctrl"]) ? "Ctrl" : "" + var/ShiftMod = text2num(href_list["shift"]) ? "Shift" : "" + var/numpad = text2num(href_list["numpad"]) ? "Numpad" : "" + // var/key_code = text2num(href_list["key_code"]) + + if(GLOB._kbMap[new_key]) + new_key = GLOB._kbMap[new_key] + + var/full_key + switch(new_key) + if("Alt") + full_key = "[new_key][CtrlMod][ShiftMod]" + if("Ctrl") + full_key = "[AltMod][new_key][ShiftMod]" + if("Shift") + full_key = "[AltMod][CtrlMod][new_key]" + else + full_key = "[AltMod][CtrlMod][ShiftMod][numpad][new_key]" + if(key_bindings[old_key]) + key_bindings[old_key] -= kb_name + if(!length(key_bindings[old_key])) + key_bindings -= old_key + key_bindings[full_key] += list(kb_name) + key_bindings[full_key] = sortList(key_bindings[full_key]) + + user << browse(null, "window=capturekeypress") + user.client.update_movement_keys() + save_preferences() + + if("keybindings_reset") + var/choice = tgalert(user, "Would you prefer 'hotkey' or 'classic' defaults?", "Setup keybindings", "Hotkey", "Classic", "Cancel") + if(choice == "Cancel") + ShowChoices(user) + return + hotkeys = (choice == "Hotkey") + key_bindings = (hotkeys) ? deepCopyList(GLOB.hotkey_keybinding_list_by_key) : deepCopyList(GLOB.classic_keybinding_list_by_key) + user.client.update_movement_keys() + if("chat_on_map") chat_on_map = !chat_on_map if("see_chat_non_mob") @@ -2303,6 +2477,9 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("ghost_pda") chat_toggles ^= CHAT_GHOSTPDA + if("income_pings") + chat_toggles ^= CHAT_BANKCARD + if("pull_requests") chat_toggles ^= CHAT_PULLR @@ -2361,21 +2538,18 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("ambientocclusion") ambientocclusion = !ambientocclusion if(parent && parent.screen && parent.screen.len) - var/obj/screen/plane_master/game_world/PM = locate(/obj/screen/plane_master/game_world) in parent.screen - PM.backdrop(parent.mob) + var/obj/screen/plane_master/game_world/G = parent.mob.hud_used.plane_masters["[GAME_PLANE]"] + var/obj/screen/plane_master/above_wall/A = parent.mob.hud_used.plane_masters["[ABOVE_WALL_PLANE]"] + var/obj/screen/plane_master/wall/W = parent.mob.hud_used.plane_masters["[WALL_PLANE]"] + G.backdrop(parent.mob) + A.backdrop(parent.mob) + W.backdrop(parent.mob) if("auto_fit_viewport") auto_fit_viewport = !auto_fit_viewport if(auto_fit_viewport && parent) parent.fit_viewport() - if("sprint_key") - sprint_spacebar = !sprint_spacebar - - if("sprint_toggle") - sprint_toggle = !sprint_toggle - - if("hud_toggle_flash") hud_toggle_flash = !hud_toggle_flash @@ -2554,3 +2728,37 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(!cached_holoform_icons[filter_type]) cached_holoform_icons[filter_type] = process_holoform_icon_filter(custom_holoform_icon, filter_type) return cached_holoform_icons[filter_type] + +//Used in savefile update 32, can be removed once that is no longer relevant. +/datum/preferences/proc/force_reset_keybindings() + var/choice = tgalert(parent.mob, "Your basic keybindings need to be reset, emotes will remain as before. Would you prefer 'hotkey' or 'classic' mode?", "Reset keybindings", "Hotkey", "Classic") + hotkeys = (choice != "Classic") + var/list/oldkeys = key_bindings + key_bindings = (hotkeys) ? deepCopyList(GLOB.hotkey_keybinding_list_by_key) : deepCopyList(GLOB.classic_keybinding_list_by_key) + + for(var/key in oldkeys) + if(!key_bindings[key]) + key_bindings[key] = oldkeys[key] + parent.update_movement_keys() + +/datum/preferences/proc/is_loadout_slot_available(slot) + var/list/L + LAZYINITLIST(L) + for(var/i in chosen_gear) + var/datum/gear/G = i + var/occupied_slots = L[slot_to_string(initial(G.category))] ? L[slot_to_string(initial(G.category))] + 1 : 1 + LAZYSET(L, slot_to_string(initial(G.category)), occupied_slots) + switch(slot) + if(SLOT_IN_BACKPACK) + if(L[slot_to_string(SLOT_IN_BACKPACK)] < BACKPACK_SLOT_AMT) + return TRUE + if(SLOT_HANDS) + if(L[slot_to_string(SLOT_HANDS)] < HANDS_SLOT_AMT) + return TRUE + else + if(L[slot_to_string(slot)] < DEFAULT_SLOT_AMT) + return TRUE + +#undef DEFAULT_SLOT_AMT +#undef HANDS_SLOT_AMT +#undef BACKPACK_SLOT_AMT diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 6872def704..a2da5d1ae2 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -5,7 +5,7 @@ // You do not need to raise this if you are adding new values that have sane defaults. // Only raise this value when changing the meaning/format/name/layout of an existing value // where you would want the updater procs below to run -#define SAVEFILE_VERSION_MAX 30 +#define SAVEFILE_VERSION_MAX 32 /* SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn @@ -42,7 +42,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car //if your savefile is 3 months out of date, then 'tough shit'. /datum/preferences/proc/update_preferences(current_version, savefile/S) - return + if(current_version < 32) //If you remove this, remove force_reset_keybindings() too. + addtimer(CALLBACK(src, .proc/force_reset_keybindings), 30) //No mob available when this is run, timer allows user choice. /datum/preferences/proc/update_character(current_version, savefile/S) if(current_version < 19) @@ -250,8 +251,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["parallax"] >> parallax S["ambientocclusion"] >> ambientocclusion S["auto_fit_viewport"] >> auto_fit_viewport - S["sprint_spacebar"] >> sprint_spacebar - S["sprint_toggle"] >> sprint_toggle S["hud_toggle_flash"] >> hud_toggle_flash S["hud_toggle_color"] >> hud_toggle_color S["menuoptions"] >> menuoptions @@ -261,6 +260,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["pda_color"] >> pda_color S["pda_skin"] >> pda_skin + // Custom hotkeys + S["key_bindings"] >> key_bindings + //citadel code S["arousable"] >> arousable S["screenshake"] >> screenshake @@ -290,13 +292,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car buttons_locked = sanitize_integer(buttons_locked, 0, 1, initial(buttons_locked)) windowflashing = sanitize_integer(windowflashing, 0, 1, initial(windowflashing)) default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot)) - toggles = sanitize_integer(toggles, 0, 65535, initial(toggles)) + toggles = sanitize_integer(toggles, 0, 16777215, initial(toggles)) clientfps = sanitize_integer(clientfps, 0, 1000, 0) parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, null) ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion)) auto_fit_viewport = sanitize_integer(auto_fit_viewport, 0, 1, initial(auto_fit_viewport)) - sprint_spacebar = sanitize_integer(sprint_spacebar, 0, 1, initial(sprint_spacebar)) - sprint_toggle = sanitize_integer(sprint_toggle, 0, 1, initial(sprint_toggle)) hud_toggle_flash = sanitize_integer(hud_toggle_flash, 0, 1, initial(hud_toggle_flash)) hud_toggle_color = sanitize_hexcolor(hud_toggle_color, 6, 1, initial(hud_toggle_color)) ghost_form = sanitize_inlist(ghost_form, GLOB.ghost_forms, initial(ghost_form)) @@ -312,12 +312,28 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car damagescreenshake = sanitize_integer(damagescreenshake, 0, 2, initial(damagescreenshake)) widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref)) autostand = sanitize_integer(autostand, 0, 1, initial(autostand)) - cit_toggles = sanitize_integer(cit_toggles, 0, 65535, initial(cit_toggles)) + cit_toggles = sanitize_integer(cit_toggles, 0, 16777215, initial(cit_toggles)) auto_ooc = sanitize_integer(auto_ooc, 0, 1, initial(auto_ooc)) no_tetris_storage = sanitize_integer(no_tetris_storage, 0, 1, initial(no_tetris_storage)) + key_bindings = sanitize_islist(key_bindings, list()) + + verify_keybindings_valid() // one of these days this will runtime and you'll be glad that i put it in a different proc so no one gets their saves wiped return 1 +/datum/preferences/proc/verify_keybindings_valid() + // Sanitize the actual keybinds to make sure they exist. + for(var/key in key_bindings) + if(!islist(key_bindings[key])) + key_bindings -= key + var/list/binds = key_bindings[key] + for(var/bind in binds) + if(!GLOB.keybindings_by_name[bind]) + binds -= bind + if(!length(binds)) + key_bindings -= key + // End + /datum/preferences/proc/save_preferences() if(!path) return 0 @@ -362,8 +378,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["parallax"], parallax) WRITE_FILE(S["ambientocclusion"], ambientocclusion) WRITE_FILE(S["auto_fit_viewport"], auto_fit_viewport) - WRITE_FILE(S["sprint_spacebar"], sprint_spacebar) - WRITE_FILE(S["sprint_toggle"], sprint_toggle) WRITE_FILE(S["hud_toggle_flash"], hud_toggle_flash) WRITE_FILE(S["hud_toggle_color"], hud_toggle_color) WRITE_FILE(S["menuoptions"], menuoptions) @@ -372,6 +386,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["pda_style"], pda_style) WRITE_FILE(S["pda_color"], pda_color) WRITE_FILE(S["pda_skin"], pda_skin) + WRITE_FILE(S["key_bindings"], key_bindings) //citadel code WRITE_FILE(S["screenshake"], screenshake) @@ -465,6 +480,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["feature_insect_wings"] >> features["insect_wings"] S["feature_insect_fluff"] >> features["insect_fluff"] S["feature_insect_markings"] >> features["insect_markings"] + S["feature_horns_color"] >> features["horns_color"] + S["feature_wings_color"] >> features["wings_color"] + //Custom names for(var/custom_name_id in GLOB.preferences_custom_names) @@ -535,10 +553,27 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car else //We have no old flavortext, default to new S["feature_flavor_text"] >> features["flavor_text"] + S["feature_ooc_notes"] >> features["ooc_notes"] + S["vore_flags"] >> vore_flags S["vore_taste"] >> vore_taste S["belly_prefs"] >> belly_prefs + //gear loadout + var/text_to_load + S["loadout"] >> text_to_load + var/list/saved_loadout_paths = splittext(text_to_load, "|") + chosen_gear = list() + gear_points = CONFIG_GET(number/initial_gear_points) + for(var/i in saved_loadout_paths) + var/datum/gear/path = text2path(i) + if(path) + var/init_cost = initial(path.cost) + if(init_cost > gear_points) + continue + chosen_gear += path + gear_points -= init_cost + //try to fix any outdated data if necessary if(needs_update >= 0) update_character(needs_update, S) //needs_update == savefile_version if we need an update (positive integer) @@ -643,6 +678,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car features["flavor_text"] = copytext(features["flavor_text"], 1, MAX_FLAVOR_LEN) + features["ooc_notes"] = copytext(features["ooc_notes"], 1, MAX_FLAVOR_LEN) joblessrole = sanitize_integer(joblessrole, 1, 3, initial(joblessrole)) //Validate job prefs @@ -698,8 +734,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["shirt_color"] , shirt_color) WRITE_FILE(S["socks"] , socks) WRITE_FILE(S["socks_color"] , socks_color) - WRITE_FILE(S["horns_color"] , features["horns_color"]) - WRITE_FILE(S["wings_color"] , features["wings_color"]) WRITE_FILE(S["backbag"] , backbag) WRITE_FILE(S["jumpsuit_style"] , jumpsuit_style) WRITE_FILE(S["uplink_loc"] , uplink_spawn_loc) @@ -715,6 +749,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["feature_lizard_body_markings"] , features["body_markings"]) WRITE_FILE(S["feature_lizard_legs"] , features["legs"]) WRITE_FILE(S["feature_deco_wings"] , features["deco_wings"]) + WRITE_FILE(S["feature_horns_color"] , features["horns_color"]) + WRITE_FILE(S["feature_wings_color"] , features["wings_color"]) WRITE_FILE(S["feature_insect_wings"] , features["insect_wings"]) WRITE_FILE(S["feature_insect_fluff"] , features["insect_fluff"]) WRITE_FILE(S["feature_insect_markings"] , features["insect_markings"]) @@ -746,6 +782,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["feature_has_womb"], features["has_womb"]) + WRITE_FILE(S["feature_ooc_notes"], features["ooc_notes"]) + //Custom names for(var/custom_name_id in GLOB.preferences_custom_names) var/savefile_slot_name = custom_name_id + "_name" //TODO remove this @@ -766,6 +804,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["vore_taste"] , vore_taste) WRITE_FILE(S["belly_prefs"] , belly_prefs) + //gear loadout + if(chosen_gear.len) + var/text_to_save = chosen_gear.Join("|") + S["loadout"] << text_to_save + else + S["loadout"] << "" //empty string to reset the value + cit_character_pref_save(S) return 1 diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm index 8f7156863d..951e36f9a6 100644 --- a/code/modules/client/preferences_toggles.dm +++ b/code/modules/client/preferences_toggles.dm @@ -250,6 +250,27 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings, listen_ooc)() /datum/verbs/menu/Settings/listen_ooc/Get_checked(client/C) return C.prefs.chat_toggles & CHAT_OOC +TOGGLE_CHECKBOX(/datum/verbs/menu/Settings, listen_looc)() + set name = "Show/Hide LOOC" + set category = "Preferences" + set desc = "Toggles seeing LocalOutOfCharacter chat" + usr.client.prefs.chat_toggles ^= CHAT_LOOC + usr.client.prefs.save_preferences() + to_chat(usr, "You will [(usr.client.prefs.chat_toggles & CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel.") + SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Seeing LOOC", "[usr.client.prefs.chat_toggles & CHAT_LOOC ? "Enabled" : "Disabled"]")) +/datum/verbs/menu/Settings/listen_ooc/Get_checked(client/C) + return C.prefs.chat_toggles & CHAT_LOOC + +TOGGLE_CHECKBOX(/datum/verbs/menu/Settings, listen_bank_card)() + set name = "Show/Hide Income Updates" + set category = "Preferences" + set desc = "Show or hide updates to your income" + usr.client.prefs.chat_toggles ^= CHAT_BANKCARD + usr.client.prefs.save_preferences() + to_chat(usr, "You will [(usr.client.prefs.chat_toggles & CHAT_BANKCARD) ? "now" : "no longer"] be notified when you get paid.") + SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Income Notifications", "[(usr.client.prefs.chat_toggles & CHAT_BANKCARD) ? "Enabled" : "Disabled"]")) +/datum/verbs/menu/Settings/listen_bank_card/Get_checked(client/C) + return C.prefs.chat_toggles & CHAT_BANKCARD GLOBAL_LIST_INIT(ghost_forms, list("ghost","ghostking","ghostian2","skeleghost","ghost_red","ghost_black", \ "ghost_blue","ghost_yellow","ghost_green","ghost_pink", \ diff --git a/code/modules/clothing/ears/_ears.dm b/code/modules/clothing/ears/_ears.dm index 1c31e19202..39d23c0107 100644 --- a/code/modules/clothing/ears/_ears.dm +++ b/code/modules/clothing/ears/_ears.dm @@ -6,6 +6,7 @@ throwforce = 0 slot_flags = ITEM_SLOT_EARS resistance_flags = NONE + custom_price = 250 /obj/item/clothing/ears/earmuffs name = "earmuffs" @@ -30,6 +31,7 @@ slot_flags = ITEM_SLOT_EARS | ITEM_SLOT_HEAD | ITEM_SLOT_NECK //Fluff item, put it whereever you want! actions_types = list(/datum/action/item_action/toggle_headphones) var/headphones_on = FALSE + custom_price = 125 /obj/item/clothing/ears/headphones/Initialize() . = ..() diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index 77f06a8a74..31e9407cdb 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -10,6 +10,55 @@ permeability_coefficient = 0.05 resistance_flags = NONE var/can_be_cut = 1 + custom_price = 1200 + custom_premium_price = 1200 + +/obj/item/toy/sprayoncan + name = "spray-on insulation applicator" + desc = "What is the number one problem facing our station today?" + icon = 'icons/obj/clothing/gloves.dmi' + icon_state = "sprayoncan" + +/obj/item/toy/sprayoncan/afterattack(atom/target, mob/living/carbon/user, proximity) + if(iscarbon(target) && proximity) + var/mob/living/carbon/C = target + var/mob/living/carbon/U = user + var/success = C.equip_to_slot_if_possible(new /obj/item/clothing/gloves/color/yellow/sprayon, ITEM_SLOT_GLOVES, TRUE, TRUE) + if(success) + if(C == user) + C.visible_message("[U] sprays their hands with glittery rubber!") + else + C.visible_message("[U] sprays glittery rubber on the hands of [C]!") + else + C.visible_message("The rubber fails to stick to [C]'s hands!") + + qdel(src) + +/obj/item/clothing/gloves/color/yellow/sprayon + desc = "How're you gonna get 'em off, nerd?" + name = "spray-on insulated gloves" + icon_state = "sprayon" + item_state = "sprayon" + permeability_coefficient = 0 + resistance_flags = ACID_PROOF + var/shocks_remaining = 10 + +/obj/item/clothing/gloves/color/yellow/sprayon/Initialize() + .=..() + ADD_TRAIT(src, TRAIT_NODROP, GLOVE_TRAIT) + +/obj/item/clothing/gloves/color/yellow/sprayon/equipped(mob/user, slot) + . = ..() + RegisterSignal(user, COMSIG_LIVING_SHOCK_PREVENTED, .proc/Shocked) + +/obj/item/clothing/gloves/color/yellow/sprayon/proc/Shocked() + shocks_remaining-- + if(shocks_remaining < 0) + qdel(src) //if we run out of uses, the gloves crumble away into nothing, just like my dreams after working with .dm + +/obj/item/clothing/gloves/color/yellow/sprayon/dropped() + .=..() + qdel(src) //loose nodrop items bad /obj/item/clothing/gloves/color/fyellow //Cheap Chinese Crap desc = "These gloves are cheap knockoffs of the coveted ones - no way this can end badly." @@ -200,6 +249,17 @@ permeability_coefficient = 0.3 resistance_flags = FIRE_PROOF | ACID_PROOF +/obj/item/clothing/gloves/color/latex/engineering + name = "tinker's gloves" + desc = "Overdesigned engineering gloves that have automated construction subrutines dialed in, allowing for faster construction while worn." + icon = 'icons/obj/clothing/clockwork_garb.dmi' + icon_state = "clockwork_gauntlets" + item_state = "clockwork_gauntlets" + siemens_coefficient = 0.8 + permeability_coefficient = 0.3 + carrytrait = TRAIT_QUICK_BUILD + custom_materials = list(/datum/material/iron=2000, /datum/material/silver=1500, /datum/material/gold = 1000) + /obj/item/clothing/gloves/color/white name = "white gloves" desc = "These look pretty fancy." diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm index d537e2fb60..b1c6746351 100644 --- a/code/modules/clothing/gloves/miscellaneous.dm +++ b/code/modules/clothing/gloves/miscellaneous.dm @@ -10,6 +10,7 @@ cold_protection = HANDS min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT strip_mod = 0.9 + custom_price = 75 /obj/item/clothing/gloves/fingerless/pugilist name = "armwraps" diff --git a/code/modules/clothing/head/beanie.dm b/code/modules/clothing/head/beanie.dm index 4117e88811..79f8931889 100644 --- a/code/modules/clothing/head/beanie.dm +++ b/code/modules/clothing/head/beanie.dm @@ -5,6 +5,7 @@ name = "white beanie" desc = "A stylish beanie. The perfect winter accessory for those with a keen fashion sense, and those who just can't handle a cold breeze on their heads." icon_state = "beanie" //Default white + custom_price = 60 /obj/item/clothing/head/beanie/black name = "black beanie" diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index ffd50cbfbe..80d0b7c8a8 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -60,6 +60,16 @@ cold_protection = HEAD min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT +/obj/item/clothing/head/hardhat/red/upgraded + name = "workplace-ready firefighter helmet" + desc = "By applying state of the art lighting technology to a fire helmet, and using photo-chemical hardening methods, this hardhat will protect you from robust workplace hazards." + icon_state = "hardhat0_purple" + item_state = "hardhat0_purple" + brightness_on = 5 + resistance_flags = FIRE_PROOF | ACID_PROOF + custom_materials = list(/datum/material/iron = 4000, /datum/material/glass = 1000, /datum/material/plastic = 3000, /datum/material/silver = 500) + hat_type = "purple" + /obj/item/clothing/head/hardhat/white icon_state = "hardhat0_white" item_state = "hardhat0_white" diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 3d744effb0..ae851ec4f1 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -58,6 +58,7 @@ desc = "A reliable, blue tinted helmet reminding you that you still owe that engineer a beer." icon_state = "blueshift" item_state = "blueshift" + custom_premium_price = 750 /obj/item/clothing/head/helmet/riot name = "riot helmet" @@ -273,7 +274,7 @@ //LightToggle -/obj/item/clothing/head/helment/ComponentInitialize() +/obj/item/clothing/head/helmet/ComponentInitialize() . = ..() AddElement(/datum/element/update_icon_updates_onmob) diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index 2cb043ba88..8627887492 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -129,6 +129,7 @@ dog_fashion = /datum/dog_fashion/head/pirate /obj/item/clothing/head/pirate/captain + name = "pirate captain hat" icon_state = "hgpiratecap" item_state = "hgpiratecap" diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 9c96223a6f..764b50de8c 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -42,6 +42,7 @@ desc = "You put the cake on your head. Brilliant." icon_state = "hardhat0_cakehat" item_state = "hardhat0_cakehat" + hat_type = "cakehat" hitsound = 'sound/weapons/tap.ogg' flags_inv = HIDEEARS|HIDEHAIR armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 144b17e510..90b3d7d86b 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -73,18 +73,26 @@ resistance_flags = FLAMMABLE actions_types = list(/datum/action/item_action/adjust) dog_fashion = /datum/dog_fashion/head/clown + var/list/clownmask_designs = list() + +/obj/item/clothing/mask/gas/clown_hat/Initialize(mapload) + .=..() + clownmask_designs = list( + "True Form" = image(icon = src.icon, icon_state = "clown"), + "The Feminist" = image(icon = src.icon, icon_state = "sexyclown"), + "The Jester" = image(icon = src.icon, icon_state = "chaos"), + "The Madman" = image(icon = src.icon, icon_state = "joker"), + "The Rainbow Color" = image(icon = src.icon, icon_state = "rainbow") + ) /obj/item/clothing/mask/gas/clown_hat/ui_action_click(mob/user) if(!istype(user) || user.incapacitated()) return - var/list/options = list() - options["True Form"] = "clown" - options["The Feminist"] = "sexyclown" - options["The Madman"] = "joker" - options["The Rainbow Color"] ="rainbow" + var/static/list/options = list("True Form" = "clown", "The Feminist" = "sexyclown", "The Madman" = "joker", + "The Rainbow Color" ="rainbow", "The Jester" = "chaos") - var/choice = input(user,"To what form do you wish to Morph this mask?","Morph Mask") in options + var/choice = show_radial_menu(user,src, clownmask_designs, custom_check = FALSE, radius = 36, require_near = TRUE) if(src && choice && !user.incapacitated() && in_range(user,src)) icon_state = options[choice] @@ -93,7 +101,7 @@ var/datum/action/A = X A.UpdateButtonIcon() to_chat(user, "Your Clown Mask has now morphed into [choice], all praise the Honkmother!") - return 1 + return TRUE /obj/item/clothing/mask/gas/sexyclown name = "sexy-clown wig and mask" @@ -113,19 +121,26 @@ flags_cover = MASKCOVERSEYES resistance_flags = FLAMMABLE actions_types = list(/datum/action/item_action/adjust) + var/list/mimemask_designs = list() + + +/obj/item/clothing/mask/gas/mime/Initialize(mapload) + .=..() + mimemask_designs = list( + "Blanc" = image(icon = src.icon, icon_state = "mime"), + "Excité" = image(icon = src.icon, icon_state = "sexymime"), + "Triste" = image(icon = src.icon, icon_state = "sadmime"), + "Effrayé" = image(icon = src.icon, icon_state = "scaredmime") + ) /obj/item/clothing/mask/gas/mime/ui_action_click(mob/user) if(!istype(user) || user.incapacitated()) return - var/list/options = list() - options["Blanc"] = "mime" - options["Triste"] = "sadmime" - options["Effrayé"] = "scaredmime" - options["Excité"] ="sexymime" + var/static/list/options = list("Blanc" = "mime", "Triste" = "sadmime", "Effrayé" = "scaredmime", "Excité" ="sexymime") - var/choice = input(user,"To what form do you wish to Morph this mask?","Morph Mask") in options + var/choice = show_radial_menu(user,src, mimemask_designs, custom_check = FALSE, radius = 36, require_near = TRUE) if(src && choice && !user.incapacitated() && in_range(user,src)) icon_state = options[choice] @@ -134,7 +149,7 @@ var/datum/action/A = X A.UpdateButtonIcon() to_chat(user, "Your Mime Mask has now morphed into [choice]!") - return 1 + return TRUE /obj/item/clothing/mask/gas/monkeymask name = "monkey mask" @@ -187,18 +202,25 @@ max_integrity = 100 actions_types = list(/datum/action/item_action/adjust) dog_fashion = null + var/list/tikimask_designs = list() +/obj/item/clothing/mask/gas/tiki_mask/Initialize(mapload) + .=..() + tikimask_designs = list( + "Original Tiki" = image(icon = src.icon, icon_state = "tiki_eyebrow"), + "Happy Tiki" = image(icon = src.icon, icon_state = "tiki_happy"), + "Confused Tiki" = image(icon = src.icon, icon_state = "tiki_confused"), + "Angry Tiki" = image(icon = src.icon, icon_state = "tiki_angry") + ) + /obj/item/clothing/mask/gas/tiki_mask/ui_action_click(mob/user) var/mob/M = usr - var/list/options = list() - options["Original Tiki"] = "tiki_eyebrow" - options["Happy Tiki"] = "tiki_happy" - options["Confused Tiki"] = "tiki_confused" - options["Angry Tiki"] ="tiki_angry" + var/static/list/options = list("Original Tiki" = "tiki_eyebrow", "Happy Tiki" = "tiki_happy", "Confused Tiki" = "tiki_confused", + "Angry Tiki" = "tiki_angry") - var/choice = input(M,"To what form do you wish to change this mask?","Morph Mask") in options + var/choice = show_radial_menu(user,src, tikimask_designs, custom_check = FALSE, radius = 36, require_near = TRUE) if(src && choice && !M.stat && in_range(M,src)) icon_state = options[choice] @@ -207,4 +229,4 @@ var/datum/action/A = X A.UpdateButtonIcon() to_chat(M, "The Tiki Mask has now changed into the [choice] Mask!") - return 1 + return TRUE diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index 3813ced2c4..11df38cfdd 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -351,30 +351,40 @@ resistance_flags = FLAMMABLE max_integrity = 100 actions_types = list(/datum/action/item_action/adjust) + var/list/papermask_designs = list() +/obj/item/clothing/mask/paper/Initialize(mapload) + .=..() + papermask_designs = list( + "Blank" = image(icon = src.icon, icon_state = "plainmask"), + "Neutral" = image(icon = src.icon, icon_state = "neutralmask"), + "Eyes" = image(icon = src.icon, icon_state = "eyemask"), + "Sleeping" = image(icon = src.icon, icon_state = "sleepingmask"), + "Heart" = image(icon = src.icon, icon_state = "heartmask"), + "Core" = image(icon = src.icon, icon_state = "coremask"), + "Plus" = image(icon = src.icon, icon_state = "plusmask"), + "Square" = image(icon = src.icon, icon_state = "squaremask"), + "Bullseye" = image(icon = src.icon, icon_state = "bullseyemask"), + "Vertical" = image(icon = src.icon, icon_state = "verticalmask"), + "Horizontal" = image(icon = src.icon, icon_state = "horizontalmask"), + "X" = image(icon = src.icon, icon_state = "xmask"), + "Bugeyes" = image(icon = src.icon, icon_state = "bugmask"), + "Double" = image(icon = src.icon, icon_state = "doublemask"), + "Mark" = image(icon = src.icon, icon_state = "markmask") + ) + /obj/item/clothing/mask/paper/ui_action_click(mob/user) if(!istype(user) || user.incapacitated()) return - var/list/options = list() - options["Blank"] = "plainmask" - options["Neutral"] = "neutralmask" - options["Eyes"] = "eyemask" - options["Sleeping"] ="sleepingmask" - options["Heart"] = "heartmask" - options["Core"] = "coremask" - options["Plus"] = "plusmask" - options["Square"] ="squaremask" - options["Bullseye"] = "bullseyemask" - options["Vertical"] = "verticalmask" - options["Horizontal"] = "horizontalmask" - options["X"] ="xmask" - options["Bugeyes"] = "bugmask" - options["Double"] = "doublemask" - options["Mark"] = "markmask" + var/static/list/options = list("Blank" = "plainmask", "Neutral" = "neutralmask", "Eyes" = "eyemask", + "Sleeping" ="sleepingmask", "Heart" = "heartmask", "Core" = "coremask", + "Plus" = "plusmask", "Square" ="squaremask", "Bullseye" = "bullseyemask", + "Vertical" = "verticalmask", "Horizontal" = "horizontalmask", "X" ="xmask", + "Bugeyes" = "bugmask", "Double" = "doublemask", "Mark" = "markmask") - var/choice = input(user,"What symbol would you want on this mask?","Morph Mask") in options + var/choice = show_radial_menu(user,src, papermask_designs, custom_check = FALSE, radius = 36, require_near = TRUE) if(src && choice && !user.incapacitated() && in_range(user,src)) icon_state = options[choice] diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index 402ea37f21..3052d7af8e 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -22,6 +22,7 @@ icon_state = "bluetie" item_state = "" //no inhands w_class = WEIGHT_CLASS_SMALL + custom_price = 60 /obj/item/clothing/neck/tie/blue name = "blue tie" @@ -87,6 +88,7 @@ /obj/item/clothing/neck/scarf //Default white color, same functionality as beanies. name = "white scarf" icon_state = "scarf" + custom_price = 60 desc = "A stylish scarf. The perfect winter accessory for those with a keen fashion sense, and those who just can't handle a cold breeze on their necks." dog_fashion = /datum/dog_fashion/head @@ -251,6 +253,40 @@ icon = 'icons/obj/clothing/neck.dmi' icon_state = "bling" +/obj/item/clothing/neck/necklace/dope/merchant + desc = "Don't ask how it works, the proof is in the holochips!" + /// scales the amount received in case an admin wants to emulate taxes/fees. + var/profit_scaling = 1 + /// toggles between sell (TRUE) and get price post-fees (FALSE) + var/selling = FALSE + +/obj/item/clothing/neck/necklace/dope/merchant/attack_self(mob/user) + . = ..() + selling = !selling + to_chat(user, "[src] has been set to [selling ? "'Sell'" : "'Get Price'"] mode.") + +/obj/item/clothing/neck/necklace/dope/merchant/afterattack(obj/item/I, mob/user, proximity) + . = ..() + if(!proximity) + return + var/datum/export_report/ex = export_item_and_contents(I, allowed_categories = (ALL), dry_run=TRUE) + var/price = 0 + for(var/x in ex.total_amount) + price += ex.total_value[x] + + if(price) + var/true_price = round(price*profit_scaling) + to_chat(user, "[selling ? "Sold" : "Getting the price of"] [I], value: [true_price] credits[I.contents.len ? " (exportable contents included)" : ""].[profit_scaling < 1 && selling ? "[round(price-true_price)] credit\s taken as processing fee\s." : ""]") + if(selling) + new /obj/item/holochip(get_turf(user),true_price) + for(var/i in ex.exported_atoms_ref) + var/atom/movable/AM = i + if(QDELETED(AM)) + continue + qdel(AM) + else + to_chat(user, "There is no export value for [I] or any items within it.") + ////////////////////////////////// //VERY SUPER BADASS NECKERCHIEFS// ////////////////////////////////// diff --git a/code/modules/clothing/outfits/vr.dm b/code/modules/clothing/outfits/vr.dm index 7a057eda41..ff4ef28649 100644 --- a/code/modules/clothing/outfits/vr.dm +++ b/code/modules/clothing/outfits/vr.dm @@ -3,15 +3,21 @@ uniform = /obj/item/clothing/under/color/random shoes = /obj/item/clothing/shoes/sneakers/black ears = /obj/item/radio/headset - id = /obj/item/card/id + id = /obj/item/card/id/locked_banking + var/starting_funds = 350 /datum/outfit/vr/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source) H.dna.species.before_equip_job(null, H) /datum/outfit/vr/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source) var/obj/item/card/id/id = H.wear_id - if (istype(id)) - id.access |= get_all_accesses() + if(!istype(id)) + return + id.access |= get_all_accesses() + if(id.registered_account) + id.registered_account.account_holder = "[H.real_name] (VR)" + if(starting_funds && id.bank_support == ID_LOCKED_BANK_ACCOUNT) //No payroll or ability to virtually transfer funds to an external account. + id.registered_account.adjust_money(starting_funds) /datum/outfit/vr/syndicate name = "Syndicate VR Operative - Basic" @@ -19,11 +25,12 @@ shoes = /obj/item/clothing/shoes/combat gloves = /obj/item/clothing/gloves/tackler/combat/insulated back = /obj/item/storage/backpack - id = /obj/item/card/id/syndicate + id = /obj/item/card/id/syndicate/locked_banking belt = /obj/item/gun/ballistic/automatic/pistol l_pocket = /obj/item/paper/fluff/vr/fluke_ops backpack_contents = list(/obj/item/storage/box/syndie=1,\ /obj/item/kitchen/knife/combat/survival) + starting_funds = 0 //Should be operating, not shopping. /datum/outfit/vr/syndicate/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source) . = ..() diff --git a/code/modules/clothing/shoes/colour.dm b/code/modules/clothing/shoes/colour.dm index df0f03f614..8cadb84cef 100644 --- a/code/modules/clothing/shoes/colour.dm +++ b/code/modules/clothing/shoes/colour.dm @@ -1,5 +1,6 @@ /obj/item/clothing/shoes/sneakers dying_key = DYE_REGISTRY_SNEAKERS + custom_price = 50 /obj/item/clothing/shoes/sneakers/black name = "black shoes" diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index b03871876f..9c6c81372a 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -71,6 +71,7 @@ equip_delay_other = 50 resistance_flags = NONE armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 40, "acid" = 75) + custom_price = 600 /obj/item/clothing/shoes/galoshes/dry name = "absorbent galoshes" @@ -180,6 +181,10 @@ name = "mining boots" desc = "Steel-toed mining boots for mining in hazardous environments. Very good at keeping toes uncrushed." icon_state = "explorer" + cold_protection = FEET|LEGS + min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT + heat_protection = FEET|LEGS + max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF /obj/item/clothing/shoes/cult @@ -378,6 +383,7 @@ /obj/item/clothing/shoes/cowboyboots name = "cowboy boots" desc = "A standard pair of brown cowboy boots." + custom_price = 60 //remember to replace these lame cosmetics with tg's YEEEEHAW counterparts. icon_state = "cowboyboots" /obj/item/clothing/shoes/cowboyboots/black diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index bc0aaf23f8..695d25dbf4 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -41,7 +41,7 @@ /obj/item/clothing/head/helmet/space/hardsuit/dropped(mob/user) ..() - if(suit) + if(suit && !ismob(loc)) //equipped() will handle mob cases, so it doesn't disengage twice. suit.RemoveHelmet() soundloop.stop(user) @@ -639,7 +639,7 @@ /obj/item/clothing/suit/space/hardsuit/ancient/mason name = "M.A.S.O.N RIG" - desc = "The Multi-Augmented Severe Operations Networked Resource Integration Gear is an man-portable tank designed for extreme environmental situations. It is excessively bulky, but rated for all but the most atomic of hazards. The specialized armor is surprisingly weak to conventional weaponry. The exo slot can attach most storge bags on to the suit." + desc = "The Multi-Augmented Severe Operations Networked Resource Integration Gear is an man-portable tank designed for extreme environmental situations. It is excessively bulky, but rated for all but the most atomic of hazards. The specialized armor is surprisingly weak to conventional weaponry. The exo slot can attach most storage bags on to the suit." icon_state = "hardsuit-ancient" item_state = "anc_hardsuit" armor = list("melee" = 20, "bullet" = 15, "laser" = 15, "energy" = 45, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) @@ -649,7 +649,6 @@ max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | IMMUTABLE_SLOW resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF - flags_1 = TESLA_IGNORE_1 /obj/item/clothing/head/helmet/space/hardsuit/ancient/mason name = "M.A.S.O.N RIG helmet" @@ -665,7 +664,6 @@ max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | ALLOWINTERNALS | SCAN_REAGENTS resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF - flags_1 = TESLA_IGNORE_1 /obj/item/clothing/head/helmet/space/hardsuit/ancient/mason/Initialize() . = ..() @@ -676,12 +674,14 @@ if (slot == SLOT_HEAD) var/datum/atom_hud/DHUD = GLOB.huds[DATA_HUD_DIAGNOSTIC_BASIC] DHUD.add_hud_to(user) + ADD_TRAIT(user, TRAIT_TESLA_SHOCKIMMUNE, "mason_hardsuit") /obj/item/clothing/head/helmet/space/hardsuit/ancient/mason/dropped(mob/living/carbon/human/user) ..() - if (user.head == src) + if (HAS_TRAIT_FROM(user, TRAIT_TESLA_SHOCKIMMUNE, "mason_hardsuit")) var/datum/atom_hud/DHUD = GLOB.huds[DATA_HUD_DIAGNOSTIC_BASIC] DHUD.remove_hud_from(user) + REMOVE_TRAIT(user, TRAIT_TESLA_SHOCKIMMUNE, "mason_hardsuit") /obj/item/clothing/suit/space/hardsuit/ancient/proc/on_mob_move() var/mob/living/carbon/human/H = loc @@ -915,8 +915,8 @@ /obj/item/clothing/head/helmet/space/hardsuit/lavaknight/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) . = ..() if(!isinhands) - var/mutable_appearance/energy_overlay = mutable_appearance(icon_file, "knight_cydonia_overlay", ABOVE_LIGHTING_LAYER) - energy_overlay.plane = ABOVE_LIGHTING_LAYER + var/mutable_appearance/energy_overlay = mutable_appearance(icon_file, "knight_cydonia_overlay", EMISSIVE_LAYER) + energy_overlay.plane = EMISSIVE_PLANE energy_overlay.color = energy_color . += energy_overlay @@ -946,8 +946,8 @@ /obj/item/clothing/suit/space/hardsuit/lavaknight/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) . = ..() if(!isinhands) - var/mutable_appearance/energy_overlay = mutable_appearance(icon_file, "knight_cydonia_overlay", ABOVE_LIGHTING_LAYER) - energy_overlay.plane = ABOVE_LIGHTING_LAYER + var/mutable_appearance/energy_overlay = mutable_appearance(icon_file, "knight_cydonia_overlay", EMISSIVE_LAYER) + energy_overlay.plane = EMISSIVE_PLANE energy_overlay.color = energy_color . += energy_overlay diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index e1deb5d28c..f4fd3f7bf3 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -395,10 +395,18 @@ Contains: actions_types = list() resistance_flags = FIRE_PROOF mutantrace_variation = NONE + var/charges = INFINITY -/obj/item/clothing/suit/space/hardsuit/ert/paranormal/Initialize() +/obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/Initialize() . = ..() - AddComponent(/datum/component/anti_magic, FALSE, FALSE, TRUE, ITEM_SLOT_HEAD) + AddComponent(/datum/component/anti_magic, FALSE, FALSE, TRUE, ITEM_SLOT_HEAD, charges, TRUE, null, CALLBACK(src, .proc/anti_magic_gone)) + +/obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/proc/anti_magic_gone() + var/mob/M = loc + if(!istype(M)) + return + do_sparks(2, TRUE, M) + M.show_message("\The [src] sparks and fizzles as its psychic wards wane away at last...", MSG_VISUAL) /obj/item/clothing/suit/space/hardsuit/ert/paranormal name = "paranormal response team suit" @@ -408,10 +416,18 @@ Contains: helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF + var/charges = INFINITY /obj/item/clothing/suit/space/hardsuit/ert/paranormal/Initialize() . = ..() - AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, ITEM_SLOT_OCLOTHING) + AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, ITEM_SLOT_OCLOTHING, charges, TRUE, null, CALLBACK(src, .proc/anti_magic_gone)) + +/obj/item/clothing/suit/space/hardsuit/ert/paranormal/proc/anti_magic_gone() + var/mob/M = loc + if(!istype(M)) + return + do_sparks(2, TRUE, M) + M.show_message("\The [src] sparks and fizzles as its anti magic wards wane away at last...", MSG_VISUAL) /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor name = "inquisitor's hardsuit" @@ -424,6 +440,19 @@ Contains: icon_state = "hardsuit0-inq" item_state = "hardsuit0-inq" +/obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor/old + desc = "Powerful wards are built into this hardsuit, protecting the user from all manner of paranormal threats. Alas, this one looks pretty worn out and rusted." + armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60) + slowdown = 0.8 + obj_flags = IMMUTABLE_SLOW //rest in peace rusty joints. + helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor/old + charges = 12 + +/obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor/old + desc = "A helmet worn by those who deal with paranormal threats for a living. Alas, this one looks pretty worn out and rusted." + armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60) + charges = 12 + /obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker name = "champion's hardsuit" desc = "Voices echo from the hardsuit, driving the user insane." @@ -437,6 +466,19 @@ Contains: icon_state = "hardsuit0-beserker" item_state = "hardsuit0-beserker" +/obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker/old + desc = "Voices echo from the hardsuit, driving the user insane. This one is pretty battle-worn, but still fearsome." + armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60) + slowdown = 0.8 + obj_flags = IMMUTABLE_SLOW //rest in peace rusty joints. + helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor/old + charges = 6 + +/obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/beserker/old + desc = "Peering into the eyes of the helmet is enough to seal damnation. This one is pretty battle-worn, but still fearsome." + armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60) + charges = 6 + /obj/item/clothing/head/helmet/space/fragile name = "emergency space helmet" desc = "A bulky, air-tight helmet meant to protect the user during emergency situations. It doesn't look very durable." @@ -477,4 +519,4 @@ Contains: name = "paramedic EVA helmet" desc = "A deep blue space helmet with a large red cross on the faceplate to designate the wearer as trained emergency medical personnel." icon_state = "paramedic-eva-helmet" - item_state = "paramedic-eva-helmet" \ No newline at end of file + item_state = "paramedic-eva-helmet" diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index bbfab5fda7..21dcd37bc2 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -49,6 +49,7 @@ desc = "A large, yet comfortable piece of armor, protecting you from some threats." icon_state = "blueshift" item_state = "blueshift" + custom_premium_price = 750 /obj/item/clothing/suit/armor/hos name = "armored greatcoat" diff --git a/code/modules/clothing/suits/cloaks.dm b/code/modules/clothing/suits/cloaks.dm index ce3d2576f9..0a3923b28c 100644 --- a/code/modules/clothing/suits/cloaks.dm +++ b/code/modules/clothing/suits/cloaks.dm @@ -76,7 +76,7 @@ icon_state = "dragon" desc = "A suit of armour fashioned from the remains of an ash drake." allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe, /obj/item/twohanded/spear) - armor = list("melee" = 70, "bullet" = 30, "laser" = 50, "energy" = 40, "bomb" = 70, "bio" = 60, "rad" = 50, "fire" = 100, "acid" = 100) + armor = list("melee" = 70, "bullet" = 20, "laser" = 35, "energy" = 25, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100) hoodtype = /obj/item/clothing/head/hooded/cloakhood/drake heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS @@ -87,7 +87,7 @@ name = "drake helm" icon_state = "dragon" desc = "The skull of a dragon." - armor = list("melee" = 70, "bullet" = 30, "laser" = 50, "energy" = 40, "bomb" = 70, "bio" = 60, "rad" = 50, "fire" = 100, "acid" = 100) + armor = list("melee" = 70, "bullet" = 20, "laser" = 35, "energy" = 25, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100) heat_protection = HEAD max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF | GOLIATH_RESISTANCE diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 6c4511324d..4fec2f59e7 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -647,6 +647,19 @@ desc = "A white winter coat hood with green markings." icon_state = "winterhood_viro" +/obj/item/clothing/suit/hooded/wintercoat/paramedic + name = "paramedic winter coat" + desc = "A winter coat with blue markings. Warm, but probably won't protect from biological agents. For the cozy doctor on the go." + icon_state = "coatparamed" + item_state = "coatparamed" + allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 50, "rad" = 0, "fire" = 0, "acid" = 45) + hoodtype = /obj/item/clothing/head/hooded/winterhood/paramedic + +/obj/item/clothing/head/hooded/winterhood/paramedic + desc = "A white winter coat hood with blue markings." + icon_state = "winterhood_paramed" + /obj/item/clothing/suit/hooded/wintercoat/science name = "science winter coat" desc = "A white winter coat with an outdated atomic model instead of a plastic zipper tab." diff --git a/code/modules/clothing/suits/reactive_armour.dm b/code/modules/clothing/suits/reactive_armour.dm index c9b7695779..98fb836c38 100644 --- a/code/modules/clothing/suits/reactive_armour.dm +++ b/code/modules/clothing/suits/reactive_armour.dm @@ -164,21 +164,21 @@ desc = "An experimental suit of armor with sensitive detectors hooked up to a huge capacitor grid, with emitters strutting out of it. Zap." siemens_coefficient = -1 reactivearmor_cooldown_duration = 20 - var/tesla_power = 25000 - var/tesla_range = 20 - var/tesla_flags = TESLA_MOB_DAMAGE | TESLA_OBJ_DAMAGE + var/zap_power = 25000 + var/zap_range = 20 + var/zap_flags = ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE var/legacy = FALSE var/legacy_dmg = 30 /obj/item/clothing/suit/armor/reactive/tesla/dropped(mob/user) ..() if(istype(user)) - user.flags_1 &= ~TESLA_IGNORE_1 + REMOVE_TRAIT(user, TRAIT_TESLA_SHOCKIMMUNE, "reactive_tesla_armor") /obj/item/clothing/suit/armor/reactive/tesla/equipped(mob/user, slot) ..() if(slot_flags & slotdefine2slotbit(slot)) //Was equipped to a valid slot for this item? - user.flags_1 |= TESLA_IGNORE_1 + ADD_TRAIT(user, TRAIT_TESLA_SHOCKIMMUNE, "reactive_tesla_armor") /obj/item/clothing/suit/armor/reactive/tesla/block_action(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(prob(hit_reaction_chance)) @@ -190,7 +190,7 @@ return owner.visible_message("[src] blocks [attack_text], sending out arcs of lightning!") if(!legacy) - tesla_zap(owner, tesla_range, tesla_power, tesla_flags) + tesla_zap(owner, zap_range, zap_power, zap_flags) else for(var/mob/living/M in view(7, owner)) if(M == owner) diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm index 24235bcbdf..e0ecf24204 100644 --- a/code/modules/clothing/under/_under.dm +++ b/code/modules/clothing/under/_under.dm @@ -32,7 +32,7 @@ /obj/item/clothing/under/attackby(obj/item/I, mob/user, params) if((has_sensor == BROKEN_SENSORS) && istype(I, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C = I - C.use(1) + I.use_tool(src, user, 0, 1) has_sensor = HAS_SENSORS to_chat(user,"You repair the suit sensors on [src] with [C].") return 1 diff --git a/code/modules/clothing/under/accessories.dm b/code/modules/clothing/under/accessories.dm index 88821e1afe..cb173f3bde 100644 --- a/code/modules/clothing/under/accessories.dm +++ b/code/modules/clothing/under/accessories.dm @@ -329,14 +329,14 @@ name = "bone talisman" desc = "A hunter's talisman, some say the old gods smile on those who wear it." icon_state = "talisman" - armor = list("melee" = 5, "bullet" = 5, "laser" = 5, "energy" = 5, "bomb" = 20, "bio" = 20, "rad" = 5, "fire" = 0, "acid" = 25) + armor = list("melee" = 5, "bullet" = 5, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 20, "rad" = 5, "fire" = 0, "acid" = 25) /obj/item/clothing/accessory/skullcodpiece name = "skull codpiece" desc = "A skull shaped ornament, intended to protect the important things in life." icon_state = "skull" above_suit = TRUE - armor = list("melee" = 5, "bullet" = 5, "laser" = 5, "energy" = 5, "bomb" = 20, "bio" = 20, "rad" = 5, "fire" = 0, "acid" = 25) + armor = list("melee" = 5, "bullet" = 5, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 20, "rad" = 5, "fire" = 0, "acid" = 25) /obj/item/clothing/accessory/skullcodpiece/fake name = "false codpiece" diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 997f10a379..cd58571251 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -87,6 +87,7 @@ icon_state = "overalls" item_state = "lb_suit" can_adjust = FALSE + custom_price = 60 /obj/item/clothing/under/misc/assistantformal name = "assistant's formal uniform" diff --git a/code/modules/clothing/under/pants.dm b/code/modules/clothing/under/pants.dm index 8aa1ee429c..46fc13d06e 100644 --- a/code/modules/clothing/under/pants.dm +++ b/code/modules/clothing/under/pants.dm @@ -3,6 +3,7 @@ body_parts_covered = GROIN|LEGS fitted = NO_FEMALE_UNIFORM can_adjust = FALSE + custom_price = 60 mutantrace_variation = STYLE_DIGITIGRADE //how do they show up on taurs otherwise? /obj/item/clothing/under/pants/classicjeans @@ -14,6 +15,7 @@ name = "Must Hang jeans" desc = "Made in the finest space jeans factory this side of Alpha Centauri." icon_state = "jeansmustang" + custom_price = 180 /obj/item/clothing/under/pants/blackjeans name = "black jeans" diff --git a/code/modules/clothing/under/skirt_dress.dm b/code/modules/clothing/under/skirt_dress.dm index e1212cf337..0d04193e1f 100644 --- a/code/modules/clothing/under/skirt_dress.dm +++ b/code/modules/clothing/under/skirt_dress.dm @@ -17,6 +17,7 @@ body_parts_covered = CHEST|GROIN|ARMS fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE + custom_price = 60 /obj/item/clothing/under/dress/skirt/red name = "red skirt" @@ -26,6 +27,7 @@ body_parts_covered = CHEST|GROIN|ARMS fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE + custom_price = 60 /obj/item/clothing/under/dress/skirt/purple name = "purple skirt" @@ -35,6 +37,7 @@ body_parts_covered = CHEST|GROIN|ARMS fitted = FEMALE_UNIFORM_TOP can_adjust = FALSE + custom_price = 60 /obj/item/clothing/under/dress/sundress name = "sundress" @@ -148,6 +151,7 @@ fitted = FEMALE_UNIFORM_TOP can_adjust = TRUE alt_covers_chest = TRUE + custom_price = 60 /obj/item/clothing/under/dress/skirt/plaid/blue name = "blue plaid skirt" diff --git a/code/modules/economy/_economy.dm b/code/modules/economy/_economy.dm new file mode 100644 index 0000000000..9bafb62eae --- /dev/null +++ b/code/modules/economy/_economy.dm @@ -0,0 +1,2 @@ +/obj/item/proc/get_item_credit_value() + return \ No newline at end of file diff --git a/code/modules/economy/account.dm b/code/modules/economy/account.dm new file mode 100644 index 0000000000..e8b6498c36 --- /dev/null +++ b/code/modules/economy/account.dm @@ -0,0 +1,120 @@ +#define DUMPTIME 3000 + +/datum/bank_account + var/account_holder = "Rusty Venture" + var/account_balance = 0 + var/datum/job/account_job + var/list/bank_cards = list() + var/add_to_accounts = TRUE + var/transferable = TRUE + var/account_id + var/being_dumped = FALSE //pink levels are rising + var/withdrawDelay = 0 + +/datum/bank_account/New(newname, job) + if(add_to_accounts) + if(!SSeconomy) + log_world("Wack") + SSeconomy.bank_accounts += src + account_holder = newname + account_job = job + account_id = rand(111111,999999) + +/datum/bank_account/Destroy() + if(add_to_accounts) + SSeconomy.bank_accounts -= src + return ..() + +/datum/bank_account/proc/dumpeet() + being_dumped = TRUE + withdrawDelay = world.time + DUMPTIME + +/datum/bank_account/proc/_adjust_money(amt) + account_balance += amt + if(account_balance < 0) + account_balance = 0 + +/datum/bank_account/proc/has_money(amt) + return account_balance >= amt + +/datum/bank_account/proc/adjust_money(amt) + if((amt < 0 && has_money(-amt)) || amt > 0) + _adjust_money(amt) + return TRUE + return FALSE + +/datum/bank_account/proc/transfer_money(datum/bank_account/from, amount) + if(!from.transferable || !from.has_money(amount)) + return FALSE + adjust_money(amount) + from.adjust_money(-amount) + return TRUE + +/datum/bank_account/proc/payday(amt_of_paychecks, free = FALSE) + var/money_to_transfer = account_job.paycheck * amt_of_paychecks + if(free) + adjust_money(money_to_transfer) + else + var/datum/bank_account/D = SSeconomy.get_dep_account(account_job.paycheck_department) + if(D) + if(!transfer_money(D, money_to_transfer)) + bank_card_talk("ERROR: Payday aborted, departmental funds insufficient.") + return FALSE + else + bank_card_talk("Payday processed, account now holds [account_balance] cr.") + return TRUE + bank_card_talk("ERROR: Payday aborted, unable to contact departmental account.") + return FALSE + +/datum/bank_account/proc/bank_card_talk(message, force) + if(!message || !bank_cards.len) + return + for(var/obj/A in bank_cards) + var/icon_source = A + /* + if(istype(A, /obj/item/card/id)) + var/obj/item/card/id/id_card = A + if(id_card.uses_overlays) + icon_source = id_card.get_cached_flat_icon() + */ + var/mob/card_holder = recursive_loc_check(A, /mob) + if(ismob(card_holder)) //If on a mob + if(!card_holder.client || (!(card_holder.client.prefs.chat_toggles & CHAT_BANKCARD) && !force)) + return + + card_holder.playsound_local(get_turf(card_holder), 'sound/machines/twobeep.ogg', 50, TRUE) + if(card_holder.can_hear()) + to_chat(card_holder, "[icon2html(icon_source, card_holder)] [message]") + else if(isturf(A.loc)) //If on the ground + for(var/mob/M in hearers(1,get_turf(A))) + if(M.client && !(M.client.prefs.chat_toggles & CHAT_BANKCARD) && !force) + return + playsound(A, 'sound/machines/twobeep.ogg', 50, TRUE) + A.audible_message("[icon2html(icon_source, hearers(A))] [message]", null, 1) + break + else + for(var/mob/M in A.loc) //If inside a container with other mobs (e.g. locker) + if(!M.client || (!(M.client.prefs.chat_toggles & CHAT_BANKCARD) && !force)) + return + M.playsound_local(get_turf(M), 'sound/machines/twobeep.ogg', 50, TRUE) + if(M.can_hear()) + to_chat(M, "[icon2html(icon_source, M)] [message]") + +/datum/bank_account/department + account_holder = "Guild Credit Agency" + var/department_id = "REPLACE_ME" + add_to_accounts = FALSE + +/datum/bank_account/department/New(dep_id, budget) + department_id = dep_id + account_balance = budget + account_holder = SSeconomy.department_accounts[dep_id] + SSeconomy.generated_accounts += src + +/datum/bank_account/remote // Bank account not belonging to the local station + add_to_accounts = FALSE + +/datum/bank_account/remote/non_transferable + transferable = FALSE + +#undef DUMPTIME diff --git a/code/modules/economy/paystand.dm b/code/modules/economy/paystand.dm new file mode 100644 index 0000000000..f674bc230d --- /dev/null +++ b/code/modules/economy/paystand.dm @@ -0,0 +1,138 @@ +/obj/machinery/paystand + name = "unregistered pay stand" + desc = "See title." + icon = 'icons/obj/economy.dmi' + icon_state = "card_scanner" + density = TRUE + anchored = TRUE + var/locked = FALSE + var/obj/item/card/id/my_card + var/obj/item/assembly/signaler/signaler //attached signaler, let people attach signalers that get activated if the user's transaction limit is achieved. + var/signaler_threshold = 0 //signaler threshold amount + var/amount_deposited = 0 //keep track of the amount deposited over time so you can pay multiple times to reach the signaler threshold + var/force_fee = 0 //replaces the "pay whatever" functionality with a set amount when non-zero. + +/obj/machinery/paystand/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/card/id)) + if(W == my_card) + if(user.a_intent == INTENT_DISARM) + var/rename_msg = stripped_input(user, "Rename the Paystand:", "Paystand Naming", name) + if(!rename_msg || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + return + name = rename_msg + return + else if(user.a_intent == INTENT_GRAB) + var/force_fee_input = input(user,"Set the fee!","Set a fee!",0) as num|null + if(isnull(force_fee_input) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + return + force_fee = force_fee_input + return + locked = !locked + to_chat(user, "You [src.locked ? "lock" : "unlock"] the paystand, protecting the bolts from [anchored ? "loosening" : "tightening"].") + return + if(!my_card) + var/obj/item/card/id/assistant_mains_need_to_die = W + if(!assistant_mains_need_to_die.registered_account) + return + var/msg = stripped_input(user, "Name of pay stand:", "Paystand Naming", "[user]'s Awesome Paystand") + if(!msg) + return + name = msg + desc = "Owned by [assistant_mains_need_to_die.registered_account.account_holder], pays directly into [user.p_their()] account." + my_card = assistant_mains_need_to_die + to_chat(user, "You link the stand to your account.") + return + var/obj/item/card/id/vbucks = W + if(vbucks.registered_account) + var/momsdebitcard = 0 + if(!force_fee) + momsdebitcard = input(user, "How much would you like to deposit?", "Money Deposit") as null|num + else + momsdebitcard = force_fee + if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + return + if(momsdebitcard < 1) + to_chat(user, "ERROR: Invalid amount designated.") + return + if(vbucks.registered_account.adjust_money(-momsdebitcard)) + purchase(vbucks.registered_account.account_holder, momsdebitcard) + to_chat(user, "Thanks for purchasing! The vendor has been informed.") + return + else + to_chat(user, "ERROR: Account has insufficient funds to make transaction.") + return + else + to_chat(user, "ERROR: No bank account assigned to identification card.") + return + if(istype(W, /obj/item/holochip)) + var/obj/item/holochip/H = W + var/cashmoney = input(user, "How much would you like to deposit?", "Money Deposit") as null|num + if(H.spend(cashmoney, FALSE)) + purchase(user, cashmoney) + to_chat(user, "Thanks for purchasing! The vendor has been informed.") + return + else + to_chat(user, "ERROR: Insufficient funds to make transaction.") + return + if(istype(W, /obj/item/stack/spacecash)) + to_chat(user, "What is this, the 2000s? We only take card here.") + return + if(istype(W, /obj/item/coin)) + to_chat(user, "What is this, the 1800s? We only take card here.") + return + if(istype(W, /obj/item/assembly/signaler)) + var/obj/item/assembly/signaler/S = W + if(S.secured) + to_chat(user, "The signaler needs to be in attachable mode to add it to the paystand!") + return + if(!my_card) + to_chat(user, "ERROR: No identification card has been assigned to this paystand yet!") + return + if(!signaler) + var/cash_limit = input(user, "Enter the minimum amount of cash needed to deposit before the signaler is activated.", "Signaler Activation Threshold") as null|num + if(cash_limit < 1) + to_chat(user, "ERROR: Invalid amount designated.") + return + if(cash_limit) + S.forceMove(src) + signaler = S + signaler_threshold = cash_limit + to_chat(user, "You attach the signaler to the paystand.") + desc += " A signaler appears to be attached to the scanner." + else + to_chat(user, "A signaler is already attached to this unit!") + + if(default_deconstruction_screwdriver(user, "card_scanner", "card_scanner", W)) + return + + else if(default_pry_open(W)) + return + + else if(default_unfasten_wrench(user, W)) + return + + else if(default_deconstruction_crowbar(W)) + return + else + return ..() + +/obj/machinery/paystand/proc/purchase(buyer, price) + my_card.registered_account.adjust_money(price) + my_card.registered_account.bank_card_talk("Purchase made at your vendor by [buyer] for [price] credits.") + amount_deposited = amount_deposited + price + if(signaler && amount_deposited >= signaler_threshold) + signaler.activate() + amount_deposited = 0 + +/obj/machinery/paystand/default_unfasten_wrench(mob/user, obj/item/I, time = 20) + if(locked) + to_chat(user, "The bolts on this paystand are currently covered!") + return FALSE + . = ..() + +/obj/machinery/paystand/examine(mob/user) + . = ..() + if(force_fee) + . += "This paystand forces a payment of [force_fee] credit\s per swipe instead of a variable amount." + if(user.get_active_held_item() == my_card) + . += "Paystands can be edited through swiping your card with different intents. Disarm allows editing the name while Grab changes payment functionality." diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm index 70b8e4873c..b0b12f3944 100644 --- a/code/modules/events/pirates.dm +++ b/code/modules/events/pirates.dm @@ -29,7 +29,9 @@ if(fake) return threat_message = new - payoff = round(SSshuttle.points * 0.80) + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + if(D) + payoff = round(D.account_balance * 0.80) threat_message.title = "Business proposition" threat_message.content = "This is [ship_name]. Pay up [payoff] credits or you'll walk the plank." threat_message.possible_answers = list("We'll pay.","No way.") @@ -38,13 +40,14 @@ /datum/round_event/pirates/proc/answered() if(threat_message && threat_message.answered == 1) - if(SSshuttle.points >= payoff) - SSshuttle.points -= payoff - priority_announce("Thanks for the credits, landlubbers.",sender_override = ship_name) - paid_off = TRUE - return - else - priority_announce("Trying to cheat us? You'll regret this!",sender_override = ship_name) + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + if(D) + if(D.adjust_money(-payoff)) + priority_announce("Thanks for the credits, landlubbers.",sender_override = ship_name) + paid_off = TRUE + return + else + priority_announce("Trying to cheat us? You'll regret this!",sender_override = ship_name) if(!shuttle_spawned) spawn_shuttle() @@ -60,7 +63,7 @@ if(!SSmapping.empty_space) SSmapping.empty_space = SSmapping.add_new_zlevel("Empty Area For Pirates", list(ZTRAIT_LINKAGE = SELFLOOPING)) - + var/datum/map_template/shuttle/pirate/default/ship = new var/x = rand(TRANSITIONEDGE,world.maxx - TRANSITIONEDGE - ship.width) var/y = rand(TRANSITIONEDGE,world.maxy - TRANSITIONEDGE - ship.height) @@ -104,9 +107,10 @@ /obj/machinery/shuttle_scrambler/process() if(active) if(is_station_level(z)) - var/siphoned = min(SSshuttle.points,siphon_per_tick) - SSshuttle.points -= siphoned - credits_stored += siphoned + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + if(D) + var/siphoned = min(D.account_balance,siphon_per_tick) + D.adjust_money(-siphoned) interrupt_research() else return @@ -142,12 +146,7 @@ new /obj/effect/temp_visual/emp(get_turf(S)) /obj/machinery/shuttle_scrambler/proc/dump_loot(mob/user) - if(credits_stored < 200) - to_chat(user,"Not enough credits to retrieve.") - return - while(credits_stored >= 200) - new /obj/item/stack/spacecash/c200(drop_location()) - credits_stored -= 200 + new /obj/item/holochip(drop_location(), credits_stored) to_chat(user,"You retrieve the siphoned credits!") credits_stored = 0 @@ -160,11 +159,12 @@ active = FALSE STOP_PROCESSING(SSobj,src) -/obj/machinery/shuttle_scrambler/update_icon_state() +/obj/machinery/shuttle_scrambler/update_overlays() + . = ..() if(active) - icon_state = "dominator-blue" - else - icon_state = "dominator" + var/mutable_appearance/M = mutable_appearance(icon, "dominator-overlay") + M.color = "#00FFFF" + . += M /obj/machinery/shuttle_scrambler/Destroy() toggle_off() @@ -459,3 +459,12 @@ /datum/export/pirate/cash/get_amount(obj/O) var/obj/item/stack/spacecash/C = O return ..() * C.amount * C.value + +/datum/export/pirate/holochip + cost = 1 + unit_name = "holochip" + export_types = list(/obj/item/holochip) + +/datum/export/pirate/holochip/get_cost(atom/movable/AM) + var/obj/item/holochip/H = AM + return H.credits diff --git a/code/modules/events/sentience.dm b/code/modules/events/sentience.dm index 5cb6c02c84..ba14a5307f 100644 --- a/code/modules/events/sentience.dm +++ b/code/modules/events/sentience.dm @@ -9,7 +9,7 @@ role_name = "random animal" var/animals = 1 var/one = "one" - /// Blacklisted mob_biotypes - Hey can we like, not have player controlled megafauna? + /// Blacklisted mob_biotypes - Hey can we like, not have player controlled megafauna? var/blacklisted_biotypes = MOB_EPIC fakeable = TRUE @@ -54,7 +54,7 @@ SG.transfer_ckey(SA, FALSE) - SA.grant_all_languages(TRUE) + SA.grant_all_languages(TRUE, FALSE, FALSE) SA.sentience_act() diff --git a/code/modules/events/shuttle_loan.dm b/code/modules/events/shuttle_loan.dm index c585961604..bf9f25cb04 100644 --- a/code/modules/events/shuttle_loan.dm +++ b/code/modules/events/shuttle_loan.dm @@ -69,7 +69,9 @@ priority_announce(thanks_msg, "Cargo shuttle commandeered by CentCom.") dispatched = 1 - SSshuttle.points += bonus_points + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + if(D) + D.adjust_money(bonus_points) endWhen = activeFor + 1 SSshuttle.supply.mode = SHUTTLE_CALL diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm index 60f2aef629..69bfa6e569 100644 --- a/code/modules/events/spacevine.dm +++ b/code/modules/events/spacevine.dm @@ -22,7 +22,8 @@ if(turfs.len) //Pick a turf to spawn at if we can var/turf/T = pick(turfs) - new /datum/spacevine_controller(T, pick(subtypesof(/datum/spacevine_mutation)), rand(30,100), rand(5,10), src) //spawn a controller at turf with randomized stats and a single random mutation + new /datum/spacevine_controller(T, list(pick(subtypesof(/datum/spacevine_mutation))), rand(30,100), rand(5,10), src) //spawn a controller at turf with randomized stats and a single random mutation + /datum/spacevine_mutation @@ -416,7 +417,6 @@ if(muts && muts.len) for(var/datum/spacevine_mutation/M in muts) M.add_mutation_to_vinepiece(SV) - return if(parent) SV.mutations |= parent.mutations var/parentcolor = parent.atom_colours[FIXED_COLOUR_PRIORITY] @@ -541,4 +541,4 @@ var/mob/living/M = A if(("vines" in M.faction) || ("plants" in M.faction)) return TRUE - return FALSE \ No newline at end of file + return FALSE diff --git a/code/modules/events/vent_clog.dm b/code/modules/events/vent_clog.dm index 77bb7661ba..48fb688d70 100644 --- a/code/modules/events/vent_clog.dm +++ b/code/modules/events/vent_clog.dm @@ -40,6 +40,7 @@ /datum/reagent/pax, /datum/reagent/consumable/laughter, /datum/reagent/concentrated_barbers_aid, + /datum/reagent/baldium, /datum/reagent/colorful_reagent, /datum/reagent/peaceborg_confuse, /datum/reagent/peaceborg_tire, diff --git a/code/modules/fields/gravity.dm b/code/modules/fields/gravity.dm index 8b16bb6487..2334a84e04 100644 --- a/code/modules/fields/gravity.dm +++ b/code/modules/fields/gravity.dm @@ -2,16 +2,17 @@ name = "modified gravity zone" setup_field_turfs = TRUE var/gravity_value = 0 - var/list/grav_components = list() + var/list/modified_turfs = list() field_shape = FIELD_SHAPE_RADIUS_SQUARE /datum/proximity_monitor/advanced/gravity/setup_field_turf(turf/T) . = ..() - grav_components[T] = T.AddComponent(/datum/component/forced_gravity,gravity_value) + T.AddElement(/datum/element/forced_gravity, gravity_value) + modified_turfs[T] = gravity_value /datum/proximity_monitor/advanced/gravity/cleanup_field_turf(turf/T) . = ..() - var/datum/component/forced_gravity/G = grav_components[T] - grav_components -= T - if(G) - qdel(G) \ No newline at end of file + if(isnull(modified_turfs[T])) + return + T.RemoveElement(/datum/element/forced_gravity, modified_turfs[T]) + modified_turfs -= T \ No newline at end of file diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index 0c2cbc0c67..2c1299f5b4 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -679,9 +679,7 @@ GLOBAL_LIST_INIT(hallucination_list, list( var/list/mob/living/carbon/people = list() var/mob/living/carbon/person = null var/datum/language/understood_language = target.get_random_understood_language() - for(var/mob/living/carbon/H in view(target)) - if(H == target) - continue + for(var/mob/living/carbon/H in view(target) - target) if(!person) person = H else @@ -1064,6 +1062,8 @@ GLOBAL_LIST_INIT(hallucination_list, list( qdel(src) /obj/effect/hallucination/danger + layer = TURF_LAYER + plane = FLOOR_PLANE var/image/image /obj/effect/hallucination/danger/proc/show_icon() @@ -1087,7 +1087,8 @@ GLOBAL_LIST_INIT(hallucination_list, list( name = "lava" /obj/effect/hallucination/danger/lava/show_icon() - image = image('icons/turf/floors/lava.dmi',src,"smooth",TURF_LAYER) + image = image('icons/turf/floors/lava.dmi',src,"smooth",layer) + image.plane = plane if(target.client) target.client.images += image @@ -1257,7 +1258,7 @@ GLOBAL_LIST_INIT(hallucination_list, list( ..() if(!target.halbody) var/list/possible_points = list() - for(var/turf/open/floor/F in view(target,world.view)) + for(var/turf/open/floor/F in target.fov_view(world.view)) possible_points += F if(possible_points.len) var/turf/open/floor/husk_point = pick(possible_points) @@ -1288,7 +1289,7 @@ GLOBAL_LIST_INIT(hallucination_list, list( set waitfor = FALSE ..() var/list/turf/startlocs = list() - for(var/turf/open/T in view(world.view+1,target)-view(world.view,target)) + for(var/turf/open/T in target.fov_view(world.view+1)-view(world.view,target)) startlocs += T if(!startlocs.len) qdel(src) diff --git a/code/modules/food_and_drinks/autobottler.dm b/code/modules/food_and_drinks/autobottler.dm index 6d5e0508a9..37b6fca2ce 100644 --- a/code/modules/food_and_drinks/autobottler.dm +++ b/code/modules/food_and_drinks/autobottler.dm @@ -7,7 +7,7 @@ "Wines", "Beers", "Brands", - "Storge", + "Storage", ) production_animation = "protolathe_n" allowed_buildtypes = AUTOBOTTLER @@ -15,4 +15,4 @@ //Brands - This is just export verson of the booze bottles //Storge - Just the bottles not booze inside //Wines - Holds wines later made by Sci nodes -//Beers - Holds beers later made by Sci nodes \ No newline at end of file +//Beers - Holds beers later made by Sci nodes diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm index 1592efb032..46600e9fee 100644 --- a/code/modules/food_and_drinks/drinks/drinks.dm +++ b/code/modules/food_and_drinks/drinks/drinks.dm @@ -147,7 +147,7 @@ return if (!(locate(/obj/structure/table) in src_location) || !(locate(/obj/structure/table) in over_location)) return - + //Are we an expert slider? var/datum/action/innate/D = get_action_of_type(user, /datum/action/innate/drink_fling) if(!D?.active) @@ -268,6 +268,7 @@ /obj/item/reagent_containers/food/drinks/ice name = "ice cup" desc = "Careful, cold ice, do not chew." + custom_price = 15 icon_state = "coffee" list_reagents = list(/datum/reagent/consumable/ice = 30) spillable = TRUE @@ -281,7 +282,7 @@ spillable = TRUE /obj/item/reagent_containers/food/drinks/mug/on_reagent_change(changetype) - cut_overlays() + cut_overlays() if(reagents.total_volume) var/mutable_appearance/MA = mutable_appearance(icon,"mugoverlay") MA.color = mix_color_from_reagents(reagents.reagent_list) @@ -302,6 +303,7 @@ list_reagents = list(/datum/reagent/consumable/hot_coco = 30, /datum/reagent/consumable/sugar = 5) foodtype = SUGAR resistance_flags = FREEZE_PROOF + custom_price = 120 /obj/item/reagent_containers/food/drinks/dry_ramen name = "cup ramen" @@ -310,6 +312,7 @@ list_reagents = list(/datum/reagent/consumable/dry_ramen = 30) foodtype = GRAIN isGlass = FALSE + custom_price = 95 /obj/item/reagent_containers/food/drinks/beer name = "space beer" @@ -317,6 +320,7 @@ icon_state = "beer" list_reagents = list(/datum/reagent/consumable/ethanol/beer = 30) foodtype = GRAIN | ALCOHOL + custom_price = 60 /obj/item/reagent_containers/food/drinks/beer/light name = "Carp Lite" @@ -417,6 +421,7 @@ custom_materials = list(/datum/material/iron=250) volume = 60 isGlass = FALSE + custom_price = 200 /obj/item/reagent_containers/food/drinks/flask/gold name = "captain's flask" @@ -447,6 +452,7 @@ reagent_flags = NONE spillable = FALSE isGlass = FALSE + custom_price = 45 /obj/item/reagent_containers/food/drinks/soda_cans/suicide_act(mob/living/carbon/user) user.visible_message("[user] is trying to eat \the [src]! It looks like [user.p_theyre()] trying to commit suicide!") diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm index ccce186304..9faf0918ab 100644 --- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm +++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm @@ -254,6 +254,7 @@ var/shortname = pickweight( list("T&T" = 1, "A&A" = 1, "Generic" = 1)) var/fullname + var/removals = GLOB.redacted_strings.Copy() switch(shortname) if("T&T") fullname = "Teal and Tealer" @@ -261,9 +262,6 @@ fullname = "Ash and Asher" if("Generic") fullname = "Nanotrasen Cheap Imitations" - var/removals = list("\[REDACTED\]", "\[EXPLETIVE DELETED\]", - "\[EXPUNGED\]", "\[INFORMATION ABOVE YOUR SECURITY CLEARANCE\]", - "\[MOVE ALONG CITIZEN\]", "\[NOTHING TO SEE HERE\]") var/chance = 50 if(prob(chance)) @@ -348,6 +346,7 @@ /obj/item/reagent_containers/food/drinks/bottle/applejack name = "Buckin' Bronco's Applejack" desc = "Kicks like a horse, tastes like an apple!" + custom_price = 100 icon_state = "applejack_bottle" list_reagents = list(/datum/reagent/consumable/ethanol/applejack = 100) foodtype = FRUIT @@ -358,6 +357,7 @@ /obj/item/reagent_containers/food/drinks/bottle/champagne name = "Eau d' Dandy Brut Champagne" desc = "Finely sourced from only the most pretentious French vineyards." + custom_premium_price = 250 icon_state = "champagne_bottle" list_reagents = list(/datum/reagent/consumable/ethanol/champagne = 100) @@ -376,6 +376,7 @@ /obj/item/reagent_containers/food/drinks/bottle/trappist name = "Mont de Requin Trappistes Bleu" desc = "Brewed in space-Belgium. Fancy!" + custom_premium_price = 170 icon_state = "trappistbottle" volume = 50 list_reagents = list(/datum/reagent/consumable/ethanol/trappist = 50) @@ -388,6 +389,7 @@ /obj/item/reagent_containers/food/drinks/bottle/orangejuice name = "orange juice" desc = "Full of vitamins and deliciousness!" + custom_price = 100 icon_state = "orangejuice" item_state = "carton" lefthand_file = 'icons/mob/inhands/equipment/kitchen_lefthand.dmi' @@ -409,6 +411,7 @@ /obj/item/reagent_containers/food/drinks/bottle/cream name = "milk cream" desc = "It's cream. Made from milk. What else did you think you'd find in there?" + custom_price = 100 icon_state = "cream" item_state = "carton" lefthand_file = 'icons/mob/inhands/equipment/kitchen_lefthand.dmi' @@ -420,6 +423,7 @@ /obj/item/reagent_containers/food/drinks/bottle/tomatojuice name = "tomato juice" desc = "Well, at least it LOOKS like tomato juice. You can't tell with all that redness." + custom_price = 100 icon_state = "tomatojuice" item_state = "carton" lefthand_file = 'icons/mob/inhands/equipment/kitchen_lefthand.dmi' @@ -431,6 +435,7 @@ /obj/item/reagent_containers/food/drinks/bottle/limejuice name = "lime juice" desc = "Sweet-sour goodness." + custom_price = 100 icon_state = "limejuice" item_state = "carton" lefthand_file = 'icons/mob/inhands/equipment/kitchen_lefthand.dmi' @@ -464,6 +469,7 @@ /obj/item/reagent_containers/food/drinks/bottle/menthol name = "menthol" desc = "Tastes naturally minty, and imparts a very mild numbing sensation." + custom_price = 100 icon_state = "mentholbox" item_state = "carton" lefthand_file = 'icons/mob/inhands/equipment/kitchen_lefthand.dmi' @@ -474,6 +480,7 @@ /obj/item/reagent_containers/food/drinks/bottle/grenadine name = "Jester Grenadine" desc = "Contains 0% real cherries!" + custom_price = 100 icon_state = "grenadine" isGlass = TRUE list_reagents = list(/datum/reagent/consumable/grenadine = 100) diff --git a/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm b/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm index defc44ed51..5ebcec91b9 100644 --- a/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm +++ b/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm @@ -11,6 +11,7 @@ spillable = TRUE resistance_flags = ACID_PROOF obj_flags = UNIQUE_RENAME + custom_price = 25 /obj/item/reagent_containers/food/drinks/drinkingglass/on_reagent_change(changetype) cut_overlays() @@ -46,6 +47,7 @@ possible_transfer_amounts = list() volume = 15 custom_materials = list(/datum/material/glass=100) + custom_price = 20 /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass/on_reagent_change(changetype) cut_overlays() diff --git a/code/modules/food_and_drinks/food/snacks_meat.dm b/code/modules/food_and_drinks/food/snacks_meat.dm index c7c74fb560..4e6be19488 100644 --- a/code/modules/food_and_drinks/food/snacks_meat.dm +++ b/code/modules/food_and_drinks/food/snacks_meat.dm @@ -57,7 +57,6 @@ /obj/item/reagent_containers/food/snacks/sushi_basic name = "funa hosomaki" desc = "A small cylindrical kudzu skin, filled with rice and fish." - icon = 'modular_citadel/icons/obj/food/food.dmi' icon_state = "sushie_basic" bonus_reagents = list(/datum/reagent/consumable/nutriment/vitamin = 2) list_reagents = list(/datum/reagent/consumable/nutriment = 4) @@ -69,7 +68,6 @@ /obj/item/reagent_containers/food/snacks/sushi_adv name = "funa nigiri" desc = "A peace of carp lightly placed on some rice." - icon = 'modular_citadel/icons/obj/food/food.dmi' icon_state = "sushie_adv" bonus_reagents = list(/datum/reagent/consumable/nutriment/vitamin = 2) list_reagents = list(/datum/reagent/consumable/nutriment = 6) @@ -81,7 +79,6 @@ /obj/item/reagent_containers/food/snacks/sushi_pro name = "funa nigiri" desc = "A well prepared peace of the best of the carp fillet placed on rice. Looks fancy and fresh!" - icon = 'modular_citadel/icons/obj/food/food.dmi' icon_state = "sushie_pro" bonus_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/nutriment/vitamin = 2) list_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/nutriment/vitamin = 2) @@ -398,6 +395,12 @@ tastes = list("milk" = 1, "beef" = 1) dried_being = /mob/living/simple_animal/cow +/obj/item/reagent_containers/food/snacks/cube/ape + name = "ape cube" + desc = "Don't add water." + tastes = list("the jungle" = 1, "bananas" = 1, "jimmies" = 1) + dried_being = /mob/living/simple_animal/hostile/gorilla + /obj/item/reagent_containers/food/snacks/cube/egg //Well eggs normally are able to hatch into small birds, this one does not. //Also in order to have a normal egg hatch you need a hen to lay the egg that is able to hatch, meaning this one is for on-demand hen needs. diff --git a/code/modules/food_and_drinks/food/snacks_other.dm b/code/modules/food_and_drinks/food/snacks_other.dm index 6feb2df524..2463ed3ced 100644 --- a/code/modules/food_and_drinks/food/snacks_other.dm +++ b/code/modules/food_and_drinks/food/snacks_other.dm @@ -215,7 +215,6 @@ /obj/item/reagent_containers/food/snacks/tobiko name = "tobiko" desc = "Spider eggs wrapped in a thin salted Kudzu pod" - icon = 'modular_citadel/icons/obj/food/food.dmi' icon_state = "sushie_egg" list_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/nutriment/vitamin = 2) filling_color = "#FF3333" // R225 G051 B051 @@ -558,7 +557,6 @@ /obj/item/reagent_containers/food/snacks/riceball name = "onigiri" desc = "A ball of rice with some light salt and a wrap of Kudzu skin." - icon = 'modular_citadel/icons/obj/food/food.dmi' icon_state = "riceball" list_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/sodiumchloride = 2) tastes = list("rice" = 3, "salt" = 1) diff --git a/code/modules/food_and_drinks/food/snacks_pastry.dm b/code/modules/food_and_drinks/food/snacks_pastry.dm index c5268380a1..48bd0f1da4 100644 --- a/code/modules/food_and_drinks/food/snacks_pastry.dm +++ b/code/modules/food_and_drinks/food/snacks_pastry.dm @@ -451,7 +451,7 @@ /obj/item/reagent_containers/food/snacks/donkpocket/initialize_cooked_food(obj/item/reagent_containers/food/snacks/donkpocket/S, cooking_efficiency = 1) . = ..() if(istype(S)) - desc = initial(desc) //reset the desc since will now cool down. + S.desc = initial(S.desc) //reset the desc since will now cool down. for(var/R in S.bonus_reagents) LAZYSET(S.cached_reagents_amount, R, S.reagents.get_reagent_amount(R)) S.previous_typepath = type diff --git a/code/modules/food_and_drinks/food/snacks_sandwichtoast.dm b/code/modules/food_and_drinks/food/snacks_sandwichtoast.dm index 3cc4cfe63f..9096429228 100644 --- a/code/modules/food_and_drinks/food/snacks_sandwichtoast.dm +++ b/code/modules/food_and_drinks/food/snacks_sandwichtoast.dm @@ -136,7 +136,6 @@ /obj/item/reagent_containers/food/snacks/tuna_sandwich name = "tuna sandwich" desc = "Both a salad and a sandwich in one." - icon = 'modular_citadel/icons/obj/food/food.dmi' icon_state = "tunasandwich" trash = /obj/item/trash/plate bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 3) diff --git a/code/modules/food_and_drinks/food/snacks_sushi.dm b/code/modules/food_and_drinks/food/snacks_sushi.dm index d16ca79001..3757759daf 100644 --- a/code/modules/food_and_drinks/food/snacks_sushi.dm +++ b/code/modules/food_and_drinks/food/snacks_sushi.dm @@ -3,7 +3,6 @@ /obj/item/reagent_containers/food/snacks/sushi_rice name = "Sushi Rice" desc = "A bowl of sticky rice for making sushi." - icon = 'modular_citadel/icons/obj/food/food.dmi' icon_state = "sushi_rice" list_reagents = list(/datum/reagent/consumable/sodiumchloride = 5) tastes = list("rice" = 5, "salt" = 1) @@ -12,7 +11,6 @@ /obj/item/reagent_containers/food/snacks/sea_weed name = "Sea Weed Sheet" desc = "A thin, light salt sheet of plant mater. This is commenly used in sushi recipes," - icon = 'modular_citadel/icons/obj/food/food.dmi' icon_state = "sea_weed" list_reagents = list(/datum/reagent/consumable/sodiumchloride = 2) tastes = list("plants" = 2, "salt" = 1) @@ -21,7 +19,6 @@ /obj/item/reagent_containers/food/snacks/tuna name = "Canned Tuna" desc = "A small can of tuna fish beloved by felines." - icon = 'modular_citadel/icons/obj/food/food.dmi' icon_state = "tuna_can" //trash = /obj/item/trash/tuna_used //I dont know if I like this idea - A Masked Cat list_reagents = list(/datum/reagent/consumable/sodiumchloride = 5, /datum/reagent/mercury = 2) @@ -32,7 +29,6 @@ /obj/item/reagent_containers/food/snacks/sushie_basic name = "Funa Hosomaki" desc = "A small cylindrical filled with rice and fish." - icon = 'modular_citadel/icons/obj/food/food.dmi' icon_state = "sushie_basic" bonus_reagents = list(/datum/reagent/consumable/nutriment/vitamin = 2) list_reagents = list(/datum/reagent/consumable/nutriment = 1) @@ -44,7 +40,6 @@ /obj/item/reagent_containers/food/snacks/sushie_adv name = "Funa Nigiri" desc = "A pice of carp lightly placed on some rice." - icon = 'modular_citadel/icons/obj/food/food.dmi' icon_state = "sushie_adv" bonus_reagents = list(/datum/reagent/consumable/nutriment/vitamin = 2) list_reagents = list(/datum/reagent/consumable/nutriment = 2) @@ -56,7 +51,6 @@ /obj/item/reagent_containers/food/snacks/sushie_pro name = "Funa Nigiri" desc = "A well prepared pice of the best of the carp fillet placed on rice. Looks fancy and fresh!" - icon = 'modular_citadel/icons/obj/food/food.dmi' icon_state = "sushie_pro" bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 2) list_reagents = list(/datum/reagent/consumable/nutriment = 8, /datum/reagent/consumable/nutriment/vitamin = 1) @@ -68,7 +62,6 @@ /obj/item/reagent_containers/food/snacks/tobiko name = "Tobiko" desc = "Spider eggs wrapped in a thin salted Kudzu pod" - icon = 'modular_citadel/icons/obj/food/food.dmi' icon_state = "sushie_egg" list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/vitamin = 2) filling_color = "#FF3333" // R225 G051 B051 @@ -78,7 +71,6 @@ /obj/item/reagent_containers/food/snacks/riceball name = "Onigiri" desc = "A ball of rice with some light salt and a wrap of Kudzu skin." - icon = 'modular_citadel/icons/obj/food/food.dmi' icon_state = "riceball" list_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/sodiumchloride = 2) tastes = list("rice" = 4, "salt" = 1) diff --git a/code/modules/food_and_drinks/food/snacks_vend.dm b/code/modules/food_and_drinks/food/snacks_vend.dm index 239dd433b0..a4d924bae4 100644 --- a/code/modules/food_and_drinks/food/snacks_vend.dm +++ b/code/modules/food_and_drinks/food/snacks_vend.dm @@ -41,6 +41,7 @@ filling_color = "#FFD700" tastes = list("salt" = 1, "crisps" = 1) foodtype = JUNKFOOD | FRIED + custom_price = 90 /obj/item/reagent_containers/food/snacks/no_raisin name = "4no raisins" @@ -68,6 +69,7 @@ junkiness = 25 filling_color = "#FFD700" foodtype = JUNKFOOD | GRAIN | SUGAR + custom_price = 30 /obj/item/reagent_containers/food/snacks/cheesiehonkers name = "cheesie honkers" @@ -79,6 +81,7 @@ filling_color = "#FFD700" tastes = list("cheese" = 5, "crisps" = 2) foodtype = JUNKFOOD | DAIRY | SUGAR + custom_price = 45 /obj/item/reagent_containers/food/snacks/syndicake name = "syndi-cakes" diff --git a/code/modules/goonchat/browserassets/html/browserOutput.html b/code/modules/goonchat/browserassets/html/browserOutput.html index 314cd42446..0acb127517 100644 --- a/code/modules/goonchat/browserassets/html/browserOutput.html +++ b/code/modules/goonchat/browserassets/html/browserOutput.html @@ -29,7 +29,7 @@ --ms
- +
diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm index 7f6d48e731..107282b642 100644 --- a/code/modules/holiday/halloween/jacqueen.dm +++ b/code/modules/holiday/halloween/jacqueen.dm @@ -38,8 +38,10 @@ health = 25 density = FALSE speech_span = "spooky" - friendly = "pets" - response_help = "chats with" + friendly_verb_continuous = "pets" + friendly_verb_simple = "pet" + response_help_continuous = "chats with" + response_help_simple = "chat with" light_range = 3 light_color = "#ff9842" var/last_poof diff --git a/code/modules/holodeck/mobs.dm b/code/modules/holodeck/mobs.dm index adac4ea7b2..121989bf1e 100644 --- a/code/modules/holodeck/mobs.dm +++ b/code/modules/holodeck/mobs.dm @@ -15,6 +15,9 @@ speak_chance = 1 turns_per_move = 2 butcher_results = list() - response_help = "pets" - response_disarm = "pushes aside" - response_harm = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "pushes aside" + response_disarm_simple = "push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" diff --git a/code/modules/hydroponics/grown/peas.dm b/code/modules/hydroponics/grown/peas.dm new file mode 100644 index 0000000000..6229d98b2c --- /dev/null +++ b/code/modules/hydroponics/grown/peas.dm @@ -0,0 +1,102 @@ +// Finally, peas. Base plant. +/obj/item/seeds/peas + name = "pack of pea pods" + desc = "These seeds grows into vitamin rich peas!" + icon_state = "seed-peas" + species = "peas" + plantname = "Pea Vines" + product = /obj/item/reagent_containers/food/snacks/grown/peas + maturation = 3 + potency = 25 + growthstages = 3 + growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi' + icon_grow = "peas-grow" + icon_dead = "peas-dead" + genes = list(/datum/plant_gene/trait/repeated_harvest) + mutatelist = list(/obj/item/seeds/peas/laugh) // TODO: Add /obj/item/seeds/peas/shoot at a later date, for the peashooter mutation line + reagents_add = list (/datum/reagent/consumable/nutriment/vitamin = 0.1, /datum/reagent/consumable/nutriment = 0.05, /datum/reagent/water = 0.05) + + +/obj/item/reagent_containers/food/snacks/grown/peas + seed = /obj/item/seeds/peas + name = "peapod" + desc = "Finally... peas." + icon_state = "peas" + filling_color = "#739122" + bitesize_mod = 1 + foodtype = VEGETABLES + tastes = list ("peas" = 1, "chalky saltiness" = 1) + wine_power = 50 + wine_flavor = "what is, distressingly, fermented peas." + // distill_regeant = /datum/reagent/saltpetre //if allowed, remove wine_power, ya dingus. + + +// Laughin' Peas +/obj/item/seeds/peas/laugh + name = "pack of laughin' peas" + desc = "These seeds give off a very soft purple glow.. they should grow into Laughin' Peas." + icon_state = "seed-laughpeas" + species = "laughpeas" + plantname = "Laughin' Peas" + product = /obj/item/reagent_containers/food/snacks/grown/laugh + maturation = 7 + potency = 10 + yield = 7 + production = 5 + growthstages = 3 + growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi' + icon_grow = "laughpeas-grow" + icon_dead = "laughpeas-dead" + genes = list (/datum/plant_gene/trait/repeated_harvest, /datum/plant_gene/trait/glow/purple) + mutatelist = list (/obj/item/seeds/peas/laugh/peace) + reagents_add = list (/datum/reagent/consumable/laughter = 0.05, /datum/reagent/consumable/sugar = 0.05, /datum/reagent/consumable/nutriment = 0.07) + rarity = 25 //It actually might make Central Command Officials loosen up a smidge, eh? + + +/obj/item/reagent_containers/food/snacks/grown/laugh + seed = /obj/item/seeds/peas/laugh + name = "pod of laughin' peas" + desc = "Ridens Cicer, guaranteed to improve your mood dramatically upon consumption!" + icon_state = "laughpeas" + filling_color = "#ee7bee" + bitesize_mod = 2 + foodtype = VEGETABLES + tastes = list ("a prancing rabbit" = 1) //Vib Ribbon sends her regards.. wherever she is. + wine_power = 90 + wine_flavor = "a vector-graphic rabbit dancing on your tongue" + + +// World Peas - Peace at last, peace at last... +/obj/item/seeds/peas/laugh/peace + name = "pack of world peas" + desc = "These rather large seeds give off a soothing blue glow..." + icon_state = "seed-worldpeas" + species = "worldpeas" + plantname = "World Peas" + product = /obj/item/reagent_containers/food/snacks/grown/peace + maturation = 20 + potency = 75 + yield = 1 + production = 10 + growthstages = 3 + growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi' + icon_grow = "worldpeas-grow" + icon_dead = "worldpeas-dead" + genes = list (/datum/plant_gene/trait/glow/blue) + reagents_add = list (/datum/reagent/pax = 0.1, /datum/reagent/drug/happiness = 0.1, /datum/reagent/consumable/nutriment = 0.15) + rarity = 50 // This absolutely will make even the most hardened Syndicate Operators relax, and lay down their arms. + + +/obj/item/reagent_containers/food/snacks/grown/peace + seed = /obj/item/seeds/peas/laugh/peace + name = "cluster of world peas" + desc = "A plant discovered through extensive genetic engineering, and iterative graft work. It's rumored to bring peace to any who consume it. In the wider AgSci community, it's attained the nickname of 'Pax Mundi'." //at last... world peas. I'm not sorry. + icon_state = "worldpeas" + filling_color = "#0099CC" + bitesize_mod = 4 + foodtype = VEGETABLES + tastes = list ("numbing tranquility" = 2, "warmth" = 1) + wine_power = 100 + wine_flavor = "mind-numbing peace and warmth" + + diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm index ef2eff707f..b18f4396d6 100644 --- a/code/modules/hydroponics/plant_genes.dm +++ b/code/modules/hydroponics/plant_genes.dm @@ -392,8 +392,7 @@ /datum/plant_gene/trait/battery/on_attackby(obj/item/reagent_containers/food/snacks/grown/G, obj/item/I, mob/user) if(istype(I, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C = I - if(C.use(5)) + if(I.use_tool(src, user, 0, 5, max_level = JOB_SKILL_EXPERT)) to_chat(user, "You add some cable to [G] and slide it inside the battery encasing.") var/obj/item/stock_parts/cell/potato/pocell = new /obj/item/stock_parts/cell/potato(user.loc) pocell.icon_state = G.icon_state diff --git a/code/modules/instruments/instruments/item.dm b/code/modules/instruments/instruments/item.dm index fa3e75e431..dde35a9f75 100644 --- a/code/modules/instruments/instruments/item.dm +++ b/code/modules/instruments/instruments/item.dm @@ -66,6 +66,11 @@ /obj/item/instrument/proc/is_tuned() return tune_time_left > 0 +/obj/item/instrument/dropped(mob/user) + . = ..() + if((loc != user) && (user.machine == src)) + user.set_machine(null) + /obj/item/instrument/interact(mob/user) ui_interact(user) diff --git a/code/modules/instruments/songs/_song.dm b/code/modules/instruments/songs/_song.dm index 30d8b7b3a7..0fb4418a30 100644 --- a/code/modules/instruments/songs/_song.dm +++ b/code/modules/instruments/songs/_song.dm @@ -222,7 +222,9 @@ tempo = sanitize_tempo(600 / bpm) /// Updates the window for our user. Override in subtypes. -/datum/song/proc/updateDialog(mob/user) +/datum/song/proc/updateDialog(mob/user = usr) + if(user.machine != src) + return ui_interact(user) /datum/song/process(wait) @@ -277,8 +279,10 @@ // subtype for handheld instruments, like violin /datum/song/handheld -/datum/song/handheld/updateDialog(mob/user) - parent.ui_interact(user || usr) +/datum/song/handheld/updateDialog(mob/user = usr) + if(user.machine != src) + return + parent.ui_interact(user) /datum/song/handheld/should_stop_playing(mob/user) . = ..() @@ -290,8 +294,10 @@ // subtype for stationary structures, like pianos /datum/song/stationary -/datum/song/stationary/updateDialog(mob/user) - parent.ui_interact(user || usr) +/datum/song/stationary/updateDialog(mob/user = usr) + if(user.machine != src) + return + parent.ui_interact(user) /datum/song/stationary/should_stop_playing(mob/user) . = ..() diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm index ef63ba97f8..384991e976 100644 --- a/code/modules/integrated_electronics/core/assemblies.dm +++ b/code/modules/integrated_electronics/core/assemblies.dm @@ -873,3 +873,8 @@ pixel_x = -31 if(WEST) pixel_x = 31 + plane = ABOVE_WALL_PLANE + +/obj/item/electronic_assembly/wallmount/Moved(atom/OldLoc, Dir, Forced = FALSE) //reset the plane if moved off the wall. + . = ..() + plane = GAME_PLANE diff --git a/code/modules/integrated_electronics/passive/power.dm b/code/modules/integrated_electronics/passive/power.dm index 4b6b8723dd..8f9a45ac4d 100644 --- a/code/modules/integrated_electronics/passive/power.dm +++ b/code/modules/integrated_electronics/passive/power.dm @@ -89,7 +89,7 @@ desc = "Produces electricity from chemicals." icon_state = "chemical_cell" extended_desc = "This is effectively an internal beaker. It will consume and produce power from plasma, slime jelly, welding fuel, carbon,\ - ethanol, nutriment, and blood in order of decreasing efficiency. It will consume fuel only if the battery can take more energy." + ethanol, nutriment, and blood in order of decreasing efficiency. It will consume fuel only if the battery can take more energy. But no fuel can be compared with blood of living human." complexity = 4 inputs = list() outputs = list("volume used" = IC_PINTYPE_NUMBER, "self reference" = IC_PINTYPE_SELFREF) @@ -102,10 +102,8 @@ var/lfwb =TRUE /obj/item/integrated_circuit/passive/power/chemical_cell/Initialize() - ..() + . = ..() create_reagents(volume, OPENCONTAINER) - extended_desc +="But no fuel can be compared with blood of living human." - /obj/item/integrated_circuit/passive/power/chemical_cell/interact(mob/user) set_pin_data(IC_OUTPUT, 2, WEAKREF(src)) diff --git a/code/modules/integrated_electronics/subtypes/converters.dm b/code/modules/integrated_electronics/subtypes/converters.dm index 8c7529651b..ebb91a894e 100644 --- a/code/modules/integrated_electronics/subtypes/converters.dm +++ b/code/modules/integrated_electronics/subtypes/converters.dm @@ -426,7 +426,7 @@ activators = list("compute abs coordinates" = IC_PINTYPE_PULSE_IN, "on convert" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH -/obj/item/integrated_circuit/converter/abs_to_rel_coords/do_work() +/obj/item/integrated_circuit/converter/rel_to_abs_coords/do_work() var/x1 = get_pin_data(IC_INPUT, 1) var/y1 = get_pin_data(IC_INPUT, 2) @@ -456,7 +456,7 @@ activators = list("compute abs coordinates" = IC_PINTYPE_PULSE_IN, "on convert" = IC_PINTYPE_PULSE_OUT) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH -/obj/item/integrated_circuit/converter/abs_to_rel_coords/do_work() +/obj/item/integrated_circuit/converter/adv_rel_to_abs_coords/do_work() var/turf/T = get_turf(src) if(!T) diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm index 49e6855b38..a0608bb5ed 100644 --- a/code/modules/integrated_electronics/subtypes/input.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -865,7 +865,7 @@ var/translated = FALSE if(speaker && message) if(raw_message) - if(message_langs != get_default_language()) + if(message_langs != get_selected_language()) translated = TRUE set_pin_data(IC_OUTPUT, 1, speaker.GetVoice()) set_pin_data(IC_OUTPUT, 2, raw_message) diff --git a/code/modules/integrated_electronics/subtypes/weaponized.dm b/code/modules/integrated_electronics/subtypes/weaponized.dm index 2f6a2cd841..3123eeabbe 100644 --- a/code/modules/integrated_electronics/subtypes/weaponized.dm +++ b/code/modules/integrated_electronics/subtypes/weaponized.dm @@ -296,6 +296,7 @@ var/x_abs = clamp(T.x + target_x_rel, 0, world.maxx) var/y_abs = clamp(T.y + target_y_rel, 0, world.maxy) var/range = round(clamp(sqrt(target_x_rel*target_x_rel+target_y_rel*target_y_rel),0,8),1) + playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 50, 1) assembly.visible_message("\The [assembly] has thrown [A]!") log_attack("[assembly] [REF(assembly)] has thrown [A] with lethal force.") A.forceMove(drop_location()) diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index e40c278e92..c700d668c5 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -56,6 +56,9 @@ //can be overridden by antag_rep.txt config var/antag_rep = 10 + var/paycheck = PAYCHECK_MINIMAL + var/paycheck_department = ACCOUNT_CIV + var/list/mind_traits // Traits added to the mind of the mob assigned this job var/list/blacklisted_quirks //list of quirk typepaths blacklisted. @@ -66,10 +69,8 @@ // How much threat this job is worth in dynamic. Is subtracted if the player's not an antag, added if they are. var/threat = 0 - /// Starting skill levels. - var/list/starting_skills - /// Skill affinities to set - var/list/skill_affinities + /// Starting skill modifiers. + var/list/starting_modifiers //Only override this proc //H is usually a human unless an /equip override transformed it @@ -104,7 +105,13 @@ /datum/job/proc/equip(mob/living/carbon/human/H, visualsOnly = FALSE, announce = TRUE, latejoin = FALSE, datum/outfit/outfit_override = null, client/preference_source) if(!H) return FALSE - + if(!visualsOnly) + var/datum/bank_account/bank_account = new(H.real_name, src) + bank_account.account_holder = H.real_name + bank_account.account_job = src + bank_account.account_id = rand(111111,999999) + bank_account.payday(STARTING_PAYCHECKS, TRUE) + H.account_id = bank_account.account_id if(CONFIG_GET(flag/enforce_human_authority) && (title in GLOB.command_positions)) if(H.dna.species.id != "human") H.set_species(/datum/species/human) @@ -171,15 +178,10 @@ to_chat(M, "Prefix your message with :h to speak on your department's radio. To see other prefixes, look closely at your headset.") /datum/job/proc/standard_assign_skills(datum/mind/M) - if(!starting_skills) + if(!starting_modifiers) return - for(var/skill in starting_skills) - M.skill_holder.boost_skill_value_to(skill, starting_skills[skill]) - // do wipe affinities though - M.skill_holder.skill_affinities = list() - for(var/skill in skill_affinities) - M.skill_holder.skill_affinities[skill] = skill_affinities[skill] - UNSETEMPTY(M.skill_holder.skill_affinities) //if we didn't set any. + for(var/mod in starting_modifiers) + ADD_SINGLETON_SKILL_MODIFIER(M, mod, null) /datum/outfit/job name = "Standard Gear" @@ -242,12 +244,18 @@ H.real_name = "[J.title] #[rand(10000, 99999)]" var/obj/item/card/id/C = H.wear_id - if(istype(C)) + if(istype(C) && C.bank_support) C.access = J.get_access() shuffle_inplace(C.access) // Shuffle access list to make NTNet passkeys less predictable C.registered_name = H.real_name C.assignment = J.title C.update_label() + for(var/A in SSeconomy.bank_accounts) + var/datum/bank_account/B = A + if(B.account_id == H.account_id) + C.registered_account = B + B.bank_cards += C + break H.sec_hud_set_ID() var/obj/item/pda/PDA = H.get_item_by_slot(pda_slot) diff --git a/code/modules/jobs/job_types/ai.dm b/code/modules/jobs/job_types/ai.dm index efe574ab66..a7401791ab 100644 --- a/code/modules/jobs/job_types/ai.dm +++ b/code/modules/jobs/job_types/ai.dm @@ -17,6 +17,8 @@ var/do_special_check = TRUE threat = 5 + starting_modifiers = list(/datum/skill_modifier/job/level/wiring/basic) + /datum/job/ai/equip(mob/living/carbon/human/H, visualsOnly, announce, latejoin, datum/outfit/outfit_override, client/preference_source = null) if(visualsOnly) CRASH("dynamic preview is unsupported") diff --git a/code/modules/jobs/job_types/assistant.dm b/code/modules/jobs/job_types/assistant.dm index c4fa213b61..91b3a3f581 100644 --- a/code/modules/jobs/job_types/assistant.dm +++ b/code/modules/jobs/job_types/assistant.dm @@ -14,6 +14,8 @@ Assistant minimal_access = list() //See /datum/job/assistant/get_access() outfit = /datum/outfit/job/assistant antag_rep = 7 + paycheck = PAYCHECK_ASSISTANT // Get a job. Job reassignment changes your paycheck now. Get over it. + paycheck_department = ACCOUNT_CIV display_order = JOB_DISPLAY_ORDER_ASSISTANT dresscodecompliant = FALSE threat = 0.2 diff --git a/code/modules/jobs/job_types/atmospheric_technician.dm b/code/modules/jobs/job_types/atmospheric_technician.dm index 66861033fd..1962b8e8a9 100644 --- a/code/modules/jobs/job_types/atmospheric_technician.dm +++ b/code/modules/jobs/job_types/atmospheric_technician.dm @@ -17,6 +17,11 @@ ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_EMERGENCY_STORAGE, ACCESS_CONSTRUCTION, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_MEDIUM + paycheck_department = ACCOUNT_ENG + + starting_modifiers = list(/datum/skill_modifier/job/level/wiring/basic, /datum/skill_modifier/job/affinity/wiring) + display_order = JOB_DISPLAY_ORDER_ATMOSPHERIC_TECHNICIAN threat = 0.5 diff --git a/code/modules/jobs/job_types/bartender.dm b/code/modules/jobs/job_types/bartender.dm index 709c53d51d..e5cd015460 100644 --- a/code/modules/jobs/job_types/bartender.dm +++ b/code/modules/jobs/job_types/bartender.dm @@ -14,6 +14,8 @@ access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_BAR, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_EASY + paycheck_department = ACCOUNT_SRV display_order = JOB_DISPLAY_ORDER_BARTENDER threat = 0.5 diff --git a/code/modules/jobs/job_types/botanist.dm b/code/modules/jobs/job_types/botanist.dm index 4cf106ea99..65f3e7ca48 100644 --- a/code/modules/jobs/job_types/botanist.dm +++ b/code/modules/jobs/job_types/botanist.dm @@ -13,6 +13,8 @@ access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_HYDROPONICS, ACCESS_MORGUE, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_EASY + paycheck_department = ACCOUNT_SRV display_order = JOB_DISPLAY_ORDER_BOTANIST threat = 1.5 // lol powergame diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm index d38a2a3ddf..3733658c33 100644 --- a/code/modules/jobs/job_types/captain.dm +++ b/code/modules/jobs/job_types/captain.dm @@ -15,11 +15,15 @@ exp_type = EXP_TYPE_COMMAND exp_type_department = EXP_TYPE_COMMAND + outfit = /datum/outfit/job/captain access = list() //See get_access() minimal_access = list() //See get_access() + paycheck = PAYCHECK_COMMAND + paycheck_department = ACCOUNT_SEC + mind_traits = list(TRAIT_CAPTAIN_METABOLISM, TRAIT_DISK_VERIFIER) display_order = JOB_DISPLAY_ORDER_CAPTAIN diff --git a/code/modules/jobs/job_types/cargo_technician.dm b/code/modules/jobs/job_types/cargo_technician.dm index d574482444..840af56a0e 100644 --- a/code/modules/jobs/job_types/cargo_technician.dm +++ b/code/modules/jobs/job_types/cargo_technician.dm @@ -14,6 +14,8 @@ access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_MAINT_TUNNELS, ACCESS_CARGO, ACCESS_MAILSORTING, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_EASY + paycheck_department = ACCOUNT_CAR display_order = JOB_DISPLAY_ORDER_CARGO_TECHNICIAN threat = 0.2 diff --git a/code/modules/jobs/job_types/chaplain.dm b/code/modules/jobs/job_types/chaplain.dm index cf9c5a6a3c..5f66519365 100644 --- a/code/modules/jobs/job_types/chaplain.dm +++ b/code/modules/jobs/job_types/chaplain.dm @@ -13,6 +13,8 @@ access = list(ACCESS_MORGUE, ACCESS_CHAPEL_OFFICE, ACCESS_CREMATORIUM, ACCESS_THEATRE) minimal_access = list(ACCESS_MORGUE, ACCESS_CHAPEL_OFFICE, ACCESS_CREMATORIUM, ACCESS_THEATRE) + paycheck = PAYCHECK_EASY + paycheck_department = ACCOUNT_CIV display_order = JOB_DISPLAY_ORDER_CHAPLAIN threat = 0.5 diff --git a/code/modules/jobs/job_types/chemist.dm b/code/modules/jobs/job_types/chemist.dm index 571785526b..b2699071e3 100644 --- a/code/modules/jobs/job_types/chemist.dm +++ b/code/modules/jobs/job_types/chemist.dm @@ -15,12 +15,13 @@ access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_CHEMISTRY, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_MEDIUM + paycheck_department = ACCOUNT_MED display_order = JOB_DISPLAY_ORDER_CHEMIST threat = 1.5 - starting_skills = list(/datum/skill/numerical/surgery = STARTING_SKILL_SURGERY_MEDICAL) - skill_affinities = list(/datum/skill/numerical/surgery = STARTING_SKILL_AFFINITY_SURGERY_MEDICAL) + starting_modifiers = list(/datum/skill_modifier/job/surgery, /datum/skill_modifier/job/affinity/surgery) /datum/outfit/job/chemist name = "Chemist" diff --git a/code/modules/jobs/job_types/chief_engineer.dm b/code/modules/jobs/job_types/chief_engineer.dm index 0d70e872ac..d8df767a9f 100644 --- a/code/modules/jobs/job_types/chief_engineer.dm +++ b/code/modules/jobs/job_types/chief_engineer.dm @@ -26,6 +26,10 @@ ACCESS_EXTERNAL_AIRLOCKS, ACCESS_ATMOSPHERICS, ACCESS_EVA, ACCESS_HEADS, ACCESS_CONSTRUCTION, ACCESS_SEC_DOORS, ACCESS_MINISAT, ACCESS_CE, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_COMMAND + paycheck_department = ACCOUNT_ENG + + starting_modifiers = list(/datum/skill_modifier/job/level/wiring, /datum/skill_modifier/job/affinity/wiring) display_order = JOB_DISPLAY_ORDER_CHIEF_ENGINEER blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/paraplegic, /datum/quirk/insanity) diff --git a/code/modules/jobs/job_types/chief_medical_officer.dm b/code/modules/jobs/job_types/chief_medical_officer.dm index 478c33551d..adee2856fa 100644 --- a/code/modules/jobs/job_types/chief_medical_officer.dm +++ b/code/modules/jobs/job_types/chief_medical_officer.dm @@ -24,13 +24,14 @@ minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_HEADS, ACCESS_MINERAL_STOREROOM, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_CMO, ACCESS_SURGERY, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_SEC_DOORS, ACCESS_MAINT_TUNNELS) + paycheck = PAYCHECK_COMMAND + paycheck_department = ACCOUNT_MED display_order = JOB_DISPLAY_ORDER_CHIEF_MEDICAL_OFFICER blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/insanity) threat = 2 - starting_skills = list(/datum/skill/numerical/surgery = STARTING_SKILL_SURGERY_MEDICAL) - skill_affinities = list(/datum/skill/numerical/surgery = STARTING_SKILL_AFFINITY_SURGERY_MEDICAL) + starting_modifiers = list(/datum/skill_modifier/job/surgery, /datum/skill_modifier/job/affinity/surgery) /datum/outfit/job/cmo name = "Chief Medical Officer" diff --git a/code/modules/jobs/job_types/clown.dm b/code/modules/jobs/job_types/clown.dm index c65c062bce..7ad7148614 100644 --- a/code/modules/jobs/job_types/clown.dm +++ b/code/modules/jobs/job_types/clown.dm @@ -13,6 +13,8 @@ access = list(ACCESS_THEATRE) minimal_access = list(ACCESS_THEATRE) + paycheck = PAYCHECK_MINIMAL + paycheck_department = ACCOUNT_SRV mind_traits = list(TRAIT_CLOWN_MENTALITY) diff --git a/code/modules/jobs/job_types/cook.dm b/code/modules/jobs/job_types/cook.dm index 20969bf1d9..5a5916cb7e 100644 --- a/code/modules/jobs/job_types/cook.dm +++ b/code/modules/jobs/job_types/cook.dm @@ -14,6 +14,8 @@ access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_EASY + paycheck_department = ACCOUNT_SRV display_order = JOB_DISPLAY_ORDER_COOK threat = 0.2 diff --git a/code/modules/jobs/job_types/curator.dm b/code/modules/jobs/job_types/curator.dm index d73d909f4f..47bfd4914a 100644 --- a/code/modules/jobs/job_types/curator.dm +++ b/code/modules/jobs/job_types/curator.dm @@ -13,6 +13,8 @@ access = list(ACCESS_LIBRARY) minimal_access = list(ACCESS_LIBRARY, ACCESS_CONSTRUCTION, ACCESS_MINING_STATION) + paycheck = PAYCHECK_EASY + paycheck_department = ACCOUNT_CIV display_order = JOB_DISPLAY_ORDER_CURATOR threat = 0.3 @@ -41,4 +43,4 @@ if(visualsOnly) return - H.grant_all_languages(omnitongue=TRUE) + H.grant_all_languages(TRUE, TRUE, TRUE, LANGUAGE_CURATOR) diff --git a/code/modules/jobs/job_types/cyborg.dm b/code/modules/jobs/job_types/cyborg.dm index f84bd0d8d6..4f74542b2a 100644 --- a/code/modules/jobs/job_types/cyborg.dm +++ b/code/modules/jobs/job_types/cyborg.dm @@ -12,6 +12,8 @@ exp_requirements = 120 exp_type = EXP_TYPE_CREW + starting_modifiers = list(/datum/skill_modifier/job/level/wiring/basic) + display_order = JOB_DISPLAY_ORDER_CYBORG /datum/job/cyborg/equip(mob/living/carbon/human/H, visualsOnly = FALSE, announce = TRUE, latejoin = FALSE, datum/outfit/outfit_override = null, client/preference_source = null) diff --git a/code/modules/jobs/job_types/detective.dm b/code/modules/jobs/job_types/detective.dm index 55c13df7a2..e5afe7e1b3 100644 --- a/code/modules/jobs/job_types/detective.dm +++ b/code/modules/jobs/job_types/detective.dm @@ -17,6 +17,8 @@ access = list(ACCESS_SEC_DOORS, ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_COURT, ACCESS_BRIG, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_SEC_DOORS, ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_COURT, ACCESS_BRIG, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_MEDIUM + paycheck_department = ACCOUNT_SEC mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) diff --git a/code/modules/jobs/job_types/geneticist.dm b/code/modules/jobs/job_types/geneticist.dm index 4fb989f6e8..a40ca0fca3 100644 --- a/code/modules/jobs/job_types/geneticist.dm +++ b/code/modules/jobs/job_types/geneticist.dm @@ -15,11 +15,13 @@ access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_CHEMISTRY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_ROBOTICS, ACCESS_MINERAL_STOREROOM, ACCESS_TECH_STORAGE) minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_MEDIUM + paycheck_department = ACCOUNT_MED display_order = JOB_DISPLAY_ORDER_GENETICIST threat = 1.5 - starting_skills = list(/datum/skill/numerical/surgery = STARTING_SKILL_SURGERY_MEDICAL) + starting_modifiers = list(/datum/skill_modifier/job/surgery, /datum/skill_modifier/job/affinity/surgery) /datum/outfit/job/geneticist name = "Geneticist" diff --git a/code/modules/jobs/job_types/head_of_personnel.dm b/code/modules/jobs/job_types/head_of_personnel.dm index b1fe3471f1..8015c19c36 100644 --- a/code/modules/jobs/job_types/head_of_personnel.dm +++ b/code/modules/jobs/job_types/head_of_personnel.dm @@ -30,6 +30,8 @@ ACCESS_CREMATORIUM, ACCESS_KITCHEN, ACCESS_HYDROPONICS, ACCESS_LAWYER, ACCESS_THEATRE, ACCESS_CHAPEL_OFFICE, ACCESS_LIBRARY, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_VAULT, ACCESS_MINING_STATION, ACCESS_HOP, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_COMMAND + paycheck_department = ACCOUNT_SRV display_order = JOB_DISPLAY_ORDER_HEAD_OF_PERSONNEL diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm index 3cf4fbb102..69ed63a514 100644 --- a/code/modules/jobs/job_types/head_of_security.dm +++ b/code/modules/jobs/job_types/head_of_security.dm @@ -27,6 +27,8 @@ ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_RESEARCH, ACCESS_ENGINE, ACCESS_MINING, ACCESS_MEDICAL, ACCESS_CONSTRUCTION, ACCESS_MAILSORTING, ACCESS_HEADS, ACCESS_HOS, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MAINT_TUNNELS, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_COMMAND + paycheck_department = ACCOUNT_SEC display_order = JOB_DISPLAY_ORDER_HEAD_OF_SECURITY blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/insanity) diff --git a/code/modules/jobs/job_types/janitor.dm b/code/modules/jobs/job_types/janitor.dm index 73028255be..2f6d6f0e32 100644 --- a/code/modules/jobs/job_types/janitor.dm +++ b/code/modules/jobs/job_types/janitor.dm @@ -13,6 +13,8 @@ access = list(ACCESS_JANITOR, ACCESS_MAINT_TUNNELS, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_JANITOR, ACCESS_MAINT_TUNNELS, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_EASY + paycheck_department = ACCOUNT_SRV display_order = JOB_DISPLAY_ORDER_JANITOR threat = 0.2 diff --git a/code/modules/jobs/job_types/lawyer.dm b/code/modules/jobs/job_types/lawyer.dm index 3f80e44492..1a7499800b 100644 --- a/code/modules/jobs/job_types/lawyer.dm +++ b/code/modules/jobs/job_types/lawyer.dm @@ -14,6 +14,8 @@ access = list(ACCESS_LAWYER, ACCESS_COURT, ACCESS_SEC_DOORS) minimal_access = list(ACCESS_LAWYER, ACCESS_COURT, ACCESS_SEC_DOORS) + paycheck = PAYCHECK_EASY + paycheck_department = ACCOUNT_CIV mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) diff --git a/code/modules/jobs/job_types/medical_doctor.dm b/code/modules/jobs/job_types/medical_doctor.dm index 0e8b2e645b..5ec4b83b2f 100644 --- a/code/modules/jobs/job_types/medical_doctor.dm +++ b/code/modules/jobs/job_types/medical_doctor.dm @@ -13,12 +13,13 @@ access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_VIROLOGY, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_MEDIUM + paycheck_department = ACCOUNT_MED display_order = JOB_DISPLAY_ORDER_MEDICAL_DOCTOR threat = 0.5 - starting_skills = list(/datum/skill/numerical/surgery = STARTING_SKILL_SURGERY_MEDICAL) - skill_affinities = list(/datum/skill/numerical/surgery = STARTING_SKILL_AFFINITY_SURGERY_MEDICAL) + starting_modifiers = list(/datum/skill_modifier/job/surgery, /datum/skill_modifier/job/affinity/surgery) /datum/outfit/job/doctor name = "Medical Doctor" diff --git a/code/modules/jobs/job_types/mime.dm b/code/modules/jobs/job_types/mime.dm index 72a6ac8e13..4ba2489ab2 100644 --- a/code/modules/jobs/job_types/mime.dm +++ b/code/modules/jobs/job_types/mime.dm @@ -13,6 +13,8 @@ access = list(ACCESS_THEATRE) minimal_access = list(ACCESS_THEATRE) + paycheck = PAYCHECK_MINIMAL + paycheck_department = ACCOUNT_SRV display_order = JOB_DISPLAY_ORDER_MIME diff --git a/code/modules/jobs/job_types/paramedic.dm b/code/modules/jobs/job_types/paramedic.dm index e8098daddc..9bdfdfe279 100644 --- a/code/modules/jobs/job_types/paramedic.dm +++ b/code/modules/jobs/job_types/paramedic.dm @@ -14,13 +14,14 @@ access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM, ACCESS_MAINT_TUNNELS) minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM, ACCESS_MAINT_TUNNELS) + paycheck = PAYCHECK_MEDIUM + paycheck_department = ACCOUNT_MED display_order = JOB_DISPLAY_ORDER_PARAMEDIC threat = 0.5 - starting_skills = list(/datum/skill/numerical/surgery = STARTING_SKILL_SURGERY_MEDICAL) - skill_affinities = list(/datum/skill/numerical/surgery = STARTING_SKILL_AFFINITY_SURGERY_MEDICAL) + starting_modifiers = list(/datum/skill_modifier/job/surgery, /datum/skill_modifier/job/affinity/surgery) /datum/outfit/job/paramedic name = "Paramedic" diff --git a/code/modules/jobs/job_types/quartermaster.dm b/code/modules/jobs/job_types/quartermaster.dm index 897defb0ea..4c6b8e064f 100644 --- a/code/modules/jobs/job_types/quartermaster.dm +++ b/code/modules/jobs/job_types/quartermaster.dm @@ -24,6 +24,8 @@ minimal_access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_QM, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_KEYCARD_AUTH, ACCESS_RC_ANNOUNCE, ACCESS_SEC_DOORS, ACCESS_HEADS) + paycheck = PAYCHECK_HARD //They can already buy stuff using cargo budget, don't give em a command-level paycheck. + paycheck_department = ACCOUNT_CAR display_order = JOB_DISPLAY_ORDER_QUARTERMASTER blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/insanity) diff --git a/code/modules/jobs/job_types/research_director.dm b/code/modules/jobs/job_types/research_director.dm index 15e5c64654..7128fbe2c7 100644 --- a/code/modules/jobs/job_types/research_director.dm +++ b/code/modules/jobs/job_types/research_director.dm @@ -28,6 +28,8 @@ ACCESS_RESEARCH, ACCESS_ROBOTICS, ACCESS_XENOBIOLOGY, ACCESS_AI_UPLOAD, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MINERAL_STOREROOM, ACCESS_TECH_STORAGE, ACCESS_MINISAT, ACCESS_MAINT_TUNNELS, ACCESS_NETWORK) + paycheck = PAYCHECK_COMMAND + paycheck_department = ACCOUNT_SCI display_order = JOB_DISPLAY_ORDER_RESEARCH_DIRECTOR blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/insanity) diff --git a/code/modules/jobs/job_types/roboticist.dm b/code/modules/jobs/job_types/roboticist.dm index f9f1d20d3b..f5ae93bb6a 100644 --- a/code/modules/jobs/job_types/roboticist.dm +++ b/code/modules/jobs/job_types/roboticist.dm @@ -15,6 +15,10 @@ access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM, ACCESS_XENOBIOLOGY, ACCESS_GENETICS) minimal_access = list(ACCESS_ROBOTICS, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_MEDIUM + paycheck_department = ACCOUNT_SCI + + starting_modifiers = list(/datum/skill_modifier/job/level/wiring, /datum/skill_modifier/job/affinity/wiring) display_order = JOB_DISPLAY_ORDER_ROBOTICIST threat = 1 diff --git a/code/modules/jobs/job_types/scientist.dm b/code/modules/jobs/job_types/scientist.dm index 9809e7b4dc..476f740b9d 100644 --- a/code/modules/jobs/job_types/scientist.dm +++ b/code/modules/jobs/job_types/scientist.dm @@ -15,6 +15,8 @@ access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_MINERAL_STOREROOM, ACCESS_TECH_STORAGE, ACCESS_GENETICS) minimal_access = list(ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_MEDIUM + paycheck_department = ACCOUNT_SCI display_order = JOB_DISPLAY_ORDER_SCIENTIST threat = 1.2 diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm index decb334423..bc6f6a94c7 100644 --- a/code/modules/jobs/job_types/security_officer.dm +++ b/code/modules/jobs/job_types/security_officer.dm @@ -17,6 +17,8 @@ access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_FORENSICS_LOCKERS, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_MINERAL_STOREROOM) // See /datum/job/officer/get_access() + paycheck = PAYCHECK_HARD + paycheck_department = ACCOUNT_SEC mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) diff --git a/code/modules/jobs/job_types/shaft_miner.dm b/code/modules/jobs/job_types/shaft_miner.dm index 9eb268895e..a09c4376fb 100644 --- a/code/modules/jobs/job_types/shaft_miner.dm +++ b/code/modules/jobs/job_types/shaft_miner.dm @@ -16,6 +16,8 @@ access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MAILSORTING, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_HARD + paycheck_department = ACCOUNT_CAR display_order = JOB_DISPLAY_ORDER_SHAFT_MINER diff --git a/code/modules/jobs/job_types/station_engineer.dm b/code/modules/jobs/job_types/station_engineer.dm index 66ddc90e9b..d3f5db7dbb 100644 --- a/code/modules/jobs/job_types/station_engineer.dm +++ b/code/modules/jobs/job_types/station_engineer.dm @@ -17,6 +17,10 @@ ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_MEDIUM + paycheck_department = ACCOUNT_ENG + + starting_modifiers = list(/datum/skill_modifier/job/level/wiring, /datum/skill_modifier/job/affinity/wiring) display_order = JOB_DISPLAY_ORDER_STATION_ENGINEER diff --git a/code/modules/jobs/job_types/virologist.dm b/code/modules/jobs/job_types/virologist.dm index 78f0ba4272..790e828931 100644 --- a/code/modules/jobs/job_types/virologist.dm +++ b/code/modules/jobs/job_types/virologist.dm @@ -15,13 +15,14 @@ access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_MEDICAL, ACCESS_VIROLOGY, ACCESS_MINERAL_STOREROOM) + paycheck = PAYCHECK_MEDIUM + paycheck_department = ACCOUNT_MED display_order = JOB_DISPLAY_ORDER_VIROLOGIST threat = 1.5 - starting_skills = list(/datum/skill/numerical/surgery = STARTING_SKILL_SURGERY_MEDICAL) - skill_affinities = list(/datum/skill/numerical/surgery = STARTING_SKILL_AFFINITY_SURGERY_MEDICAL) + starting_modifiers = list(/datum/skill_modifier/job/surgery, /datum/skill_modifier/job/affinity/surgery) /datum/outfit/job/virologist name = "Virologist" diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm index 15d839ac48..5762731f62 100644 --- a/code/modules/jobs/job_types/warden.dm +++ b/code/modules/jobs/job_types/warden.dm @@ -18,6 +18,9 @@ access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_FORENSICS_LOCKERS, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_MINERAL_STOREROOM) // See /datum/job/warden/get_access() + paycheck = PAYCHECK_HARD + paycheck_department = ACCOUNT_SEC + mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) display_order = JOB_DISPLAY_ORDER_WARDEN diff --git a/code/modules/keybindings/bindings_admin.dm b/code/modules/keybindings/bindings_admin.dm deleted file mode 100644 index ca232adbe0..0000000000 --- a/code/modules/keybindings/bindings_admin.dm +++ /dev/null @@ -1,24 +0,0 @@ -/datum/admins/key_down(_key, client/user) - switch(_key) - if("F3") - user.get_admin_say() - return - if("F5") - user.admin_ghost() - return - if("F6") - player_panel_new() - return - if("F7") - user.togglebuildmodeself() - return - if("F8") - if(user.keys_held["Ctrl"]) - user.stealth() - else - user.invisimin() - return - if("F10") - user.get_dead_say() - return - ..() diff --git a/code/modules/keybindings/bindings_atom.dm b/code/modules/keybindings/bindings_atom.dm index 5f3e879237..47d6b16feb 100644 --- a/code/modules/keybindings/bindings_atom.dm +++ b/code/modules/keybindings/bindings_atom.dm @@ -5,7 +5,7 @@ if(!user.keys_held["Ctrl"]) var/movement_dir = NONE for(var/_key in user.keys_held) - movement_dir = movement_dir | SSinput.movement_keys[_key] + movement_dir = movement_dir | user.movement_keys[_key] if(user.next_move_dir_add) movement_dir |= user.next_move_dir_add if(user.next_move_dir_sub) diff --git a/code/modules/keybindings/bindings_carbon.dm b/code/modules/keybindings/bindings_carbon.dm deleted file mode 100644 index e344bc9d20..0000000000 --- a/code/modules/keybindings/bindings_carbon.dm +++ /dev/null @@ -1,9 +0,0 @@ -/mob/living/carbon/key_down(_key, client/user) - switch(_key) - if("R", "Southwest") // Southwest is End - toggle_throw_mode() - return - if("C") - user_toggle_intentional_combat_mode() - return - return ..() \ No newline at end of file diff --git a/code/modules/keybindings/bindings_client.dm b/code/modules/keybindings/bindings_client.dm index 6030362a61..a73dd9a59b 100644 --- a/code/modules/keybindings/bindings_client.dm +++ b/code/modules/keybindings/bindings_client.dm @@ -33,55 +33,69 @@ to_chat(src, "Invalid KeyDown detected! You have been disconnected from the server automatically.") log_admin("Client [ckey] just attempted to send an invalid keypress. Keymessage was over [MAX_KEYPRESS_COMMANDLENGTH] characters, autokicking due to likely abuse.") message_admins("Client [ckey] just attempted to send an invalid keypress. Keymessage was over [MAX_KEYPRESS_COMMANDLENGTH] characters, autokicking due to likely abuse.") - QDEL_IN(src, 1) + qdel(src) + return + + if(_key == "Tab") + ForceAllKeysUp() //groan, more hacky kevcode return if(length(keys_held) > MAX_HELD_KEYS) keys_held.Cut(1,2) keys_held[_key] = TRUE - var/movement = SSinput.movement_keys[_key] + var/movement = movement_keys[_key] if(!(next_move_dir_sub & movement) && !keys_held["Ctrl"]) next_move_dir_add |= movement // Client-level keybindings are ones anyone should be able to do at any time // Things like taking screenshots, hitting tab, and adminhelps. - + var/AltMod = keys_held["Alt"] ? "Alt" : "" + var/CtrlMod = keys_held["Ctrl"] ? "Ctrl" : "" + var/ShiftMod = keys_held["Shift"] ? "Shift" : "" + var/full_key switch(_key) - if("F1") - if(keys_held["Ctrl"] && keys_held["Shift"]) // Is this command ever used? - winset(src, null, "command=.options") - else - get_adminhelp() - return - if("F2") // Screenshot. Hold shift to choose a name and location to save in - winset(src, null, "command=.screenshot [!keys_held["shift"] ? "auto" : ""]") - return - if("F12") // Toggles minimal HUD - mob.button_pressed_F12() - return + if("Alt", "Ctrl", "Shift") + full_key = "[AltMod][CtrlMod][ShiftMod]" + else + full_key = "[AltMod][CtrlMod][ShiftMod][_key]" + var/keycount = 0 + for(var/kb_name in prefs.key_bindings[full_key]) + keycount++ + var/datum/keybinding/kb = GLOB.keybindings_by_name[kb_name] + if(kb.can_use(src) && kb.down(src) && keycount >= MAX_COMMANDS_PER_KEY) + break - if(holder) - holder.key_down(_key, src) - if(mob.focus) - mob.focus.key_down(_key, src) + holder?.key_down(_key, src) + mob.focus?.key_down(_key, src) + +/// Keyup's all keys held down. +/client/proc/ForceAllKeysUp() + // simulate a user releasing all keys except for the mod keys. groan. i hate this. thanks, byond. why aren't keyups able to be forced to fire on macro change aoaoaoao. + // groan + for(var/key in keys_held) // all of these won't be the 3 mod keys. + if((key == "Ctrl") || (key == "Alt") || (key == "Shift")) + continue + keyUp("[key]") /client/verb/keyUp(_key as text) set instant = TRUE set hidden = TRUE keys_held -= _key - var/movement = SSinput.movement_keys[_key] + var/movement = movement_keys[_key] if(!(next_move_dir_add & movement)) next_move_dir_sub |= movement - if(holder) - holder.key_up(_key, src) - if(mob.focus) - mob.focus.key_up(_key, src) + // We don't do full key for release, because for mod keys you + // can hold different keys and releasing any should be handled by the key binding specifically + for (var/kb_name in prefs.key_bindings[_key]) + var/datum/keybinding/kb = GLOB.keybindings_by_name[kb_name] + if(kb.can_use(src) && kb.up(src)) + break + holder?.key_up(_key, src) + mob.focus?.key_up(_key, src) // Called every game tick /client/keyLoop() - if(holder) - holder.keyLoop(src) - if(mob.focus) - mob.focus.keyLoop(src) \ No newline at end of file + holder?.keyLoop(src) + mob.focus?.keyLoop(src) diff --git a/code/modules/keybindings/bindings_human.dm b/code/modules/keybindings/bindings_human.dm deleted file mode 100644 index 9569de338c..0000000000 --- a/code/modules/keybindings/bindings_human.dm +++ /dev/null @@ -1,80 +0,0 @@ -/mob/living/carbon/human/key_down(_key, client/user) - if(client.keys_held["Shift"]) - switch(_key) - if("E") // Put held thing in belt or take out most recent thing from belt - var/obj/item/thing = get_active_held_item() - var/obj/item/storage/equipped_belt = get_item_by_slot(SLOT_BELT) - if(!equipped_belt) // We also let you equip a belt like this - if(!thing) - to_chat(user, "You have no belt to take something out of.") - return - equip_to_slot_if_possible(thing, SLOT_BELT) - return - if(!istype(equipped_belt)) // not a storage item - if(!thing) - to_chat(user, "You have no belt to take something out of.") - else - to_chat(user, "You can't fit anything in.") - return - if(thing) // put thing in belt - if(!SEND_SIGNAL(equipped_belt, COMSIG_TRY_STORAGE_INSERT, thing, user.mob)) - to_chat(user, "You can't fit anything in.") - return - if(!equipped_belt.contents.len) // nothing to take out - to_chat(user, "There's nothing in your belt to take out.") - return - var/obj/item/stored = equipped_belt.contents[equipped_belt.contents.len] - if(!stored || stored.on_found(src)) - return - stored.attack_hand(src) // take out thing from belt - return - - if("B") // Put held thing in backpack or take out most recent thing from backpack - var/obj/item/thing = get_active_held_item() - var/obj/item/storage/equipped_backpack = get_item_by_slot(SLOT_BACK) - if(!equipped_backpack) // We also let you equip a backpack like this - if(!thing) - to_chat(user, "You have no backpack to take something out of.") - return - equip_to_slot_if_possible(thing, SLOT_BACK) - return - if(!istype(equipped_backpack)) // not a storage item - if(!thing) - to_chat(user, "You have no backpack to take something out of.") - else - to_chat(user, "You can't fit anything in.") - return - if(thing) // put thing in backpack - if(!SEND_SIGNAL(equipped_backpack, COMSIG_TRY_STORAGE_INSERT, thing, user.mob)) - to_chat(user, "You can't fit anything in.") - return - if(!equipped_backpack.contents.len) // nothing to take out - to_chat(user, "There's nothing in your backpack to take out.") - return - var/obj/item/stored = equipped_backpack.contents[equipped_backpack.contents.len] - if(!stored || stored.on_found(src)) - return - stored.attack_hand(src) // take out thing from backpack - return - switch(_key) - if("Shift") - if(!user.prefs.sprint_spacebar) - user.prefs.sprint_toggle ? default_toggle_sprint() : sprint_hotkey(TRUE) //Yes, this looks hacky. Yes, this works. - return - if("Space") - if(user.prefs.sprint_spacebar) - user.prefs.sprint_toggle ? default_toggle_sprint() : sprint_hotkey(TRUE) - return - return ..() - -/mob/living/carbon/human/key_up(_key, client/user) - switch(_key) - if("Shift") - if(!user.prefs.sprint_spacebar && !user.prefs.sprint_toggle) - sprint_hotkey(FALSE) - return - if("Space") - if(user.prefs.sprint_spacebar && !user.prefs.sprint_toggle) - sprint_hotkey(FALSE) - return - return ..() diff --git a/code/modules/keybindings/bindings_robot.dm b/code/modules/keybindings/bindings_robot.dm deleted file mode 100644 index 29fb36fa65..0000000000 --- a/code/modules/keybindings/bindings_robot.dm +++ /dev/null @@ -1,22 +0,0 @@ -/mob/living/silicon/robot/key_down(_key, client/user) - switch(_key) - if("1", "2", "3") - toggle_module(text2num(_key)) - return - if("4") - a_intent_change(INTENT_HOTKEY_LEFT) - return - if("Q") - uneq_active() - return - if("Shift") - sprint_hotkey(TRUE) - return - return ..() - -/mob/living/silicon/robot/key_up(_key, client/user) - switch(_key) - if("Shift") - sprint_hotkey(FALSE) - return - return ..() diff --git a/code/modules/keybindings/focus.dm b/code/modules/keybindings/focus.dm index 205b293e9a..d542b49267 100644 --- a/code/modules/keybindings/focus.dm +++ b/code/modules/keybindings/focus.dm @@ -1,6 +1,3 @@ -/mob - var/datum/focus //What receives our keyboard inputs. src by default - /mob/proc/set_focus(datum/new_focus) if(focus == new_focus) return diff --git a/code/modules/keybindings/keybind/__defines.dm b/code/modules/keybindings/keybind/__defines.dm new file mode 100644 index 0000000000..baa095987c --- /dev/null +++ b/code/modules/keybindings/keybind/__defines.dm @@ -0,0 +1,20 @@ +#define CATEGORY_CLIENT "CLIENT" +#define CATEGORY_EMOTE "EMOTE" +#define CATEGORY_ADMIN "ADMIN" +#define CATEGORY_XENO "XENO" +#define CATEGORY_CARBON "CARBON" +#define CATEGORY_HUMAN "HUMAN" +#define CATEGORY_ROBOT "ROBOT" +#define CATEGORY_MISC "MISC" +#define CATEGORY_MOVEMENT "MOVEMENT" +#define CATEGORY_TARGETING "TARGETING" + +#define WEIGHT_HIGHEST 0 +#define WEIGHT_ADMIN 10 +#define WEIGHT_CLIENT 20 +#define WEIGHT_ROBOT 30 +#define WEIGHT_MOB 40 +#define WEIGHT_LIVING 50 +#define WEIGHT_DEAD 60 +#define WEIGHT_EMOTE 70 +#define WEIGHT_LOWEST 999 diff --git a/code/modules/keybindings/keybind/_keybind.dm b/code/modules/keybindings/keybind/_keybind.dm new file mode 100644 index 0000000000..1d68e2d037 --- /dev/null +++ b/code/modules/keybindings/keybind/_keybind.dm @@ -0,0 +1,24 @@ +/datum/keybinding + var/list/hotkey_keys + var/list/classic_keys + var/name + var/full_name + var/description = "" + var/category = CATEGORY_MISC + var/weight = WEIGHT_LOWEST + var/keybind_signal + +/datum/keybinding/New() + + // Default keys to the master "hotkey_keys" + if(LAZYLEN(hotkey_keys) && !LAZYLEN(classic_keys)) + classic_keys = hotkey_keys.Copy() + +/datum/keybinding/proc/down(client/user) + return FALSE + +/datum/keybinding/proc/up(client/user) + return FALSE + +/datum/keybinding/proc/can_use(client/user) + return TRUE diff --git a/code/modules/keybindings/keybind/admin.dm b/code/modules/keybindings/keybind/admin.dm new file mode 100644 index 0000000000..b63221e97a --- /dev/null +++ b/code/modules/keybindings/keybind/admin.dm @@ -0,0 +1,96 @@ +/datum/keybinding/admin + category = CATEGORY_ADMIN + weight = WEIGHT_ADMIN + +/datum/keybinding/admin/can_use(client/user) + return user.holder ? TRUE : FALSE + +/datum/keybinding/admin/admin_say + hotkey_keys = list("F3") + name = "admin_say" + full_name = "Admin say" + description = "Talk with other admins." + +/datum/keybinding/admin/admin_say/down(client/user) + user.get_admin_say() + return TRUE + +/datum/keybinding/admin/admin_ghost + hotkey_keys = list("F5") + name = "admin_ghost" + full_name = "Aghost" + description = "Go ghost" + +/datum/keybinding/admin/admin_ghost/down(client/user) + user.admin_ghost() + return TRUE + +/datum/keybinding/admin/player_panel_new + hotkey_keys = list("F6") + name = "player_panel_new" + full_name = "Player Panel New" + description = "Opens up the new player panel" + +/datum/keybinding/admin/player_panel_new/down(client/user) + user.holder.player_panel_new() + return TRUE + +/datum/keybinding/admin/toggle_buildmode_self + hotkey_keys = list("F7") + name = "toggle_buildmode_self" + full_name = "Toggle Buildmode Self" + description = "Toggles buildmode" + +/datum/keybinding/admin/toggle_buildmode_self/down(client/user) + user.togglebuildmodeself() + return TRUE + +/datum/keybinding/admin/stealthmode + hotkey_keys = list("CtrlF8") + name = "stealth_mode" + full_name = "Stealth mode" + description = "Enters stealth mode" + +/datum/keybinding/admin/stealthmode/down(client/user) + user.stealth() + return TRUE + +/datum/keybinding/admin/invisimin + hotkey_keys = list("F8") + name = "invisimin" + full_name = "Admin invisibility" + description = "Toggles ghost-like invisibility (Don't abuse this)" + +/datum/keybinding/admin/invisimin/down(client/user) + user.invisimin() + return TRUE + +/datum/keybinding/admin/deadsay + hotkey_keys = list("F10") + name = "dsay" + full_name = "deadsay" + description = "Allows you to send a message to dead chat" + +/datum/keybinding/admin/deadsay/down(client/user) + user.get_dead_say() + return TRUE + +/datum/keybinding/admin/deadmin + hotkey_keys = list("Unbound") + name = "deadmin" + full_name = "Deadmin" + description = "Shed your admin powers" + +/datum/keybinding/admin/deadmin/down(client/user) + user.deadmin() + return TRUE + +/datum/keybinding/admin/readmin + hotkey_keys = list("Unbound") + name = "readmin" + full_name = "Readmin" + description = "Regain your admin powers" + +/datum/keybinding/admin/readmin/down(client/user) + user.readmin() + return TRUE diff --git a/code/modules/keybindings/keybind/carbon.dm b/code/modules/keybindings/keybind/carbon.dm new file mode 100644 index 0000000000..46cb5cd0ac --- /dev/null +++ b/code/modules/keybindings/keybind/carbon.dm @@ -0,0 +1,62 @@ +/datum/keybinding/carbon + category = CATEGORY_CARBON + weight = WEIGHT_MOB + +/datum/keybinding/carbon/can_use(client/user) + return iscarbon(user.mob) + +/datum/keybinding/carbon/toggle_throw_mode + hotkey_keys = list("R", "Southwest") // END + name = "toggle_throw_mode" + full_name = "Toggle throw mode" + description = "Toggle throwing the current item or not." + category = CATEGORY_CARBON + +/datum/keybinding/carbon/toggle_throw_mode/down(client/user) + var/mob/living/carbon/C = user.mob + C.toggle_throw_mode() + return TRUE + +/datum/keybinding/carbon/select_help_intent + hotkey_keys = list("1") + name = "select_help_intent" + full_name = "Select help intent" + description = "" + category = CATEGORY_CARBON + +/datum/keybinding/carbon/select_help_intent/down(client/user) + user.mob?.a_intent_change(INTENT_HELP) + return TRUE + +/datum/keybinding/carbon/select_disarm_intent + hotkey_keys = list("2") + name = "select_disarm_intent" + full_name = "Select disarm intent" + description = "" + category = CATEGORY_CARBON + +/datum/keybinding/carbon/select_disarm_intent/down(client/user) + user.mob?.a_intent_change(INTENT_DISARM) + return TRUE + +/datum/keybinding/carbon/select_grab_intent + hotkey_keys = list("3") + name = "select_grab_intent" + full_name = "Select grab intent" + description = "" + category = CATEGORY_CARBON + +/datum/keybinding/carbon/select_grab_intent/down(client/user) + user.mob?.a_intent_change(INTENT_GRAB) + return TRUE + +/datum/keybinding/carbon/select_harm_intent + hotkey_keys = list("4") + name = "select_harm_intent" + full_name = "Select harm intent" + description = "" + category = CATEGORY_CARBON + +/datum/keybinding/carbon/select_harm_intent/down(client/user) + user.mob?.a_intent_change(INTENT_HARM) + return TRUE diff --git a/code/modules/keybindings/keybind/client.dm b/code/modules/keybindings/keybind/client.dm new file mode 100644 index 0000000000..1d44efa063 --- /dev/null +++ b/code/modules/keybindings/keybind/client.dm @@ -0,0 +1,33 @@ +/datum/keybinding/client + category = CATEGORY_CLIENT + weight = WEIGHT_HIGHEST + +/datum/keybinding/client/admin_help + hotkey_keys = list("F1") + name = "admin_help" + full_name = "Admin Help" + description = "Ask an admin for help." + +/datum/keybinding/client/admin_help/down(client/user) + user.get_adminhelp() + return TRUE + +/datum/keybinding/client/screenshot + hotkey_keys = list("F2") + name = "screenshot" + full_name = "Screenshot" + description = "Take a screenshot." + +/datum/keybinding/client/screenshot/down(client/user) + winset(user, null, "command=.screenshot [!user.keys_held["shift"] ? "auto" : ""]") + return TRUE + +/datum/keybinding/client/minimal_hud + hotkey_keys = list("F12") + name = "minimal_hud" + full_name = "Minimal HUD" + description = "Hide most HUD features" + +/datum/keybinding/client/minimal_hud/down(client/user) + user.mob.button_pressed_F12() + return TRUE diff --git a/code/modules/keybindings/keybind/emote.dm b/code/modules/keybindings/keybind/emote.dm new file mode 100644 index 0000000000..6099826819 --- /dev/null +++ b/code/modules/keybindings/keybind/emote.dm @@ -0,0 +1,15 @@ +/datum/keybinding/emote + category = CATEGORY_EMOTE + weight = WEIGHT_EMOTE + var/emote_key + +/datum/keybinding/emote/proc/link_to_emote(datum/emote/faketype) + hotkey_keys = list("Unbound") + emote_key = initial(faketype.key) + name = initial(faketype.key) + full_name = capitalize(initial(faketype.key)) + description = "Do the emote '*[emote_key]'" + +/datum/keybinding/emote/down(client/user) + . = ..() + return user.mob.emote(emote_key, intentional=TRUE) diff --git a/code/modules/keybindings/keybind/human.dm b/code/modules/keybindings/keybind/human.dm new file mode 100644 index 0000000000..43f5653472 --- /dev/null +++ b/code/modules/keybindings/keybind/human.dm @@ -0,0 +1,39 @@ +/datum/keybinding/human + category = CATEGORY_HUMAN + weight = WEIGHT_MOB + +/datum/keybinding/human/can_use(client/user) + return ishuman(user.mob) + +/datum/keybinding/human/quick_equip + hotkey_keys = list("E") + name = "quick_equip" + full_name = "Quick Equip" + description = "Quickly puts an item in the best slot available" + +/datum/keybinding/human/quick_equip/down(client/user) + var/mob/living/carbon/human/H = user.mob + H.quick_equip() + return TRUE + +/datum/keybinding/human/quick_equipbelt + hotkey_keys = list("ShiftE") + name = "quick_equipbelt" + full_name = "Quick equip belt" + description = "Put held thing in belt or take out most recent thing from belt" + +/datum/keybinding/human/quick_equipbelt/down(client/user) + var/mob/living/carbon/human/H = user.mob + H.smart_equipbelt() + return TRUE + +/datum/keybinding/human/bag_equip + hotkey_keys = list("ShiftB") + name = "bag_equip" + full_name = "Bag equip" + description = "Put held thing in backpack or take out most recent thing from backpack" + +/datum/keybinding/human/bag_equip/down(client/user) + var/mob/living/carbon/human/H = user.mob + H.smart_equipbag() + return TRUE diff --git a/code/modules/keybindings/keybind/living.dm b/code/modules/keybindings/keybind/living.dm new file mode 100644 index 0000000000..0408d0889b --- /dev/null +++ b/code/modules/keybindings/keybind/living.dm @@ -0,0 +1,41 @@ +/datum/keybinding/living + category = CATEGORY_HUMAN + weight = WEIGHT_MOB + +/datum/keybinding/living/can_use(client/user) + return isliving(user.mob) + +/datum/keybinding/living/resist + hotkey_keys = list("B") + name = "resist" + full_name = "Resist" + description = "Break free of your current state. Handcuffed? on fire? Resist!" + +/datum/keybinding/living/resist/down(client/user) + var/mob/living/L = user.mob + L.resist() + return TRUE + +/datum/keybinding/living/toggle_combat_mode + hotkey_keys = list("C") + name = "toggle_combat_mode" + full_name = "Toggle combat mode" + description = "Toggles whether or not you're in combat mode." + +/datum/keybinding/living/toggle_combat_mode/can_use(client/user) + return iscarbon(user.mob) // for now, only carbons should be using combat mode, although all livings have combat mode implemented. + +/datum/keybinding/living/toggle_combat_mode/down(client/user) + var/mob/living/carbon/C = user.mob + C.user_toggle_intentional_combat_mode() + return TRUE + +/datum/keybinding/living/toggle_resting + hotkey_keys = list("V") + name = "toggle_resting" + full_name = "Toggle Resting" + description = "Toggles whether or not you are intentionally laying down." + +/datum/keybinding/living/toggle_resting/down(client/user) + var/mob/living/L = user.mob + L.lay_down() diff --git a/code/modules/keybindings/keybind/mob.dm b/code/modules/keybindings/keybind/mob.dm new file mode 100644 index 0000000000..083d4a19fd --- /dev/null +++ b/code/modules/keybindings/keybind/mob.dm @@ -0,0 +1,123 @@ +/datum/keybinding/mob + category = CATEGORY_HUMAN + weight = WEIGHT_MOB + +/datum/keybinding/mob/stop_pulling + hotkey_keys = list("H", "Delete") + name = "stop_pulling" + full_name = "Stop pulling" + description = "" + +/datum/keybinding/mob/stop_pulling/down(client/user) + var/mob/M = user.mob + if(!M.pulling) + to_chat(user, "You are not pulling anything.") + else + M.stop_pulling() + return TRUE + +/datum/keybinding/mob/cycle_intent_right + hotkey_keys = list("Northwest", "F") // HOME + name = "cycle_intent_right" + full_name = "Cycle Action Intent Right" + description = "" + +/datum/keybinding/mob/cycle_intent_right/down(client/user) + var/mob/M = user.mob + M.a_intent_change(INTENT_HOTKEY_RIGHT) + return TRUE + +/datum/keybinding/mob/cycle_intent_left + hotkey_keys = list("Insert", "G") + name = "cycle_intent_left" + full_name = "Cycle Action Intent Left" + description = "" + +/datum/keybinding/mob/cycle_intent_left/down(client/user) + var/mob/M = user.mob + M.a_intent_change(INTENT_HOTKEY_LEFT) + return TRUE + +/datum/keybinding/mob/swap_hands + hotkey_keys = list("X", "Northeast") // PAGEUP + name = "swap_hands" + full_name = "Swap hands" + description = "" + +/datum/keybinding/mob/swap_hands/down(client/user) + var/mob/M = user.mob + M.swap_hand() + return TRUE + +/datum/keybinding/mob/activate_inhand + hotkey_keys = list("Z", "Southeast") // PAGEDOWN + name = "activate_inhand" + full_name = "Activate in-hand" + description = "Uses whatever item you have inhand" + +/datum/keybinding/mob/activate_inhand/down(client/user) + var/mob/M = user.mob + M.mode() + return TRUE + +/datum/keybinding/mob/drop_item + hotkey_keys = list("Q") + name = "drop_item" + full_name = "Drop Item" + description = "" + +/datum/keybinding/mob/drop_item/down(client/user) + if(iscyborg(user.mob)) //cyborgs can't drop items + return FALSE + var/mob/M = user.mob + var/obj/item/I = M.get_active_held_item() + if(!I) + to_chat(user, "You have nothing to drop in your hand!") + else + user.mob.dropItemToGround(I) + return TRUE + +/datum/keybinding/mob/say_with_indicator + hotkey_keys = list("CtrlT") + classic_keys = list() + name = "say_with_indicator" + full_name = "Say with Typing Indicator" + +/datum/keybinding/mob/say_with_indicator/down(client/user) + var/mob/M = user.mob + M.say_typing_indicator() + return TRUE + +/datum/keybinding/mob/me_with_indicator + hotkey_keys = list("CtrlM") + classic_keys = list() + name = "me_with_indicator" + full_name = "Me (emote) with Typing Indicator" + +/datum/keybinding/mob/me_with_indicator/down(client/user) + var/mob/M = user.mob + M.me_typing_indicator() + return TRUE + +/datum/keybinding/living/subtle + hotkey_keys = list("5") + classic_keys = list() + name = "subtle_emote" + full_name = "Subtle Emote" + +/datum/keybinding/living/subtle/down(client/user) + var/mob/living/L = user.mob + L.subtle_keybind() + return TRUE + +/datum/keybinding/mob/whisper + hotkey_keys = list("Y") + classic_keys = list() + name = "whisper" + full_name = "Whisper" + +/datum/keybinding/mob/whisper/down(client/user) + var/mob/M = user.mob + M.whisper_keybind() + return TRUE + diff --git a/code/modules/keybindings/keybind/movement.dm b/code/modules/keybindings/keybind/movement.dm new file mode 100644 index 0000000000..176e6b9fb8 --- /dev/null +++ b/code/modules/keybindings/keybind/movement.dm @@ -0,0 +1,187 @@ +/datum/keybinding/movement + category = CATEGORY_MOVEMENT + weight = WEIGHT_HIGHEST + +/datum/keybinding/movement/north + hotkey_keys = list("W", "North") + name = "North" + full_name = "Move North" + description = "Moves your character north" + +/datum/keybinding/movement/south + hotkey_keys = list("S", "South") + name = "South" + full_name = "Move South" + description = "Moves your character south" + +/datum/keybinding/movement/west + hotkey_keys = list("A", "West") + name = "West" + full_name = "Move West" + description = "Moves your character left" + +/datum/keybinding/movement/east + hotkey_keys = list("D", "East") + name = "East" + full_name = "Move East" + description = "Moves your character east" + +/datum/keybinding/mob/face_north + hotkey_keys = list("CtrlW", "CtrlNorth") + name = "face_north" + full_name = "Face North" + description = "" + category = CATEGORY_MOVEMENT + +/datum/keybinding/mob/face_north/down(client/user) + var/mob/M = user.mob + M.northface() + return TRUE + +/datum/keybinding/mob/face_east + hotkey_keys = list("CtrlD", "CtrlEast") + name = "face_east" + full_name = "Face East" + description = "" + category = CATEGORY_MOVEMENT + +/datum/keybinding/mob/face_east/down(client/user) + var/mob/M = user.mob + M.eastface() + return TRUE + +/datum/keybinding/mob/face_south + hotkey_keys = list("CtrlS", "CtrlSouth") + name = "face_south" + full_name = "Face South" + description = "" + category = CATEGORY_MOVEMENT + +/datum/keybinding/mob/face_south/down(client/user) + var/mob/M = user.mob + M.southface() + return TRUE + +/datum/keybinding/mob/face_west + hotkey_keys = list("CtrlA", "CtrlWest") + name = "face_west" + full_name = "Face West" + description = "" + category = CATEGORY_MOVEMENT + +/datum/keybinding/mob/face_west/down(client/user) + var/mob/M = user.mob + M.westface() + return TRUE + +/datum/keybinding/mob/shift_north + hotkey_keys = list("CtrlShiftW", "CtrlShiftNorth") + name = "pixel_shift_north" + full_name = "Pixel Shift North" + description = "" + category = CATEGORY_MOVEMENT + +/datum/keybinding/mob/shift_north/down(client/user) + var/mob/M = user.mob + M.northshift() + return TRUE + +/datum/keybinding/mob/shift_east + hotkey_keys = list("CtrlShiftD", "CtrlShiftEast") + name = "pixel_shift_east" + full_name = "Pixel Shift East" + description = "" + category = CATEGORY_MOVEMENT + +/datum/keybinding/mob/shift_east/down(client/user) + var/mob/M = user.mob + M.eastshift() + return TRUE + +/datum/keybinding/mob/shift_south + hotkey_keys = list("CtrlShiftS", "CtrlShiftSouth") + name = "pixel_shift_south" + full_name = "Pixel Shift South" + description = "" + category = CATEGORY_MOVEMENT + +/datum/keybinding/mob/shift_south/down(client/user) + var/mob/M = user.mob + M.southshift() + return TRUE + +/datum/keybinding/mob/shift_west + hotkey_keys = list("CtrlShiftA", "CtrlShiftWest") + name = "pixel_shift_west" + full_name = "Pixel Shift West" + description = "" + category = CATEGORY_MOVEMENT + +/datum/keybinding/mob/shift_west/down(client/user) + var/mob/M = user.mob + M.westshift() + return TRUE + +/datum/keybinding/living/hold_sprint + hotkey_keys = list("Shift") + name = "hold_sprint" + full_name = "Sprint (hold down)" + description = "Hold down to sprint" + category = CATEGORY_MOVEMENT + +/datum/keybinding/living/hold_sprint/can_use(client/user) + return ishuman(user.mob) || iscyborg(user.mob) + +/datum/keybinding/living/hold_sprint/down(client/user) + var/mob/living/L = user.mob + L.sprint_hotkey(TRUE) + return TRUE + +/datum/keybinding/living/hold_sprint/up(client/user) + var/mob/living/L = user.mob + L.sprint_hotkey(FALSE) + return TRUE + +/datum/keybinding/living/toggle_sprint + hotkey_keys = list() + name = "toggle_sprint" + full_name = "Sprint (toggle)" + description = "Press to toggle sprint" + category = CATEGORY_MOVEMENT + +/datum/keybinding/living/toggle_sprint/can_use(client/user) + return ishuman(user.mob) || iscyborg(user.mob) + +/datum/keybinding/living/toggle_sprint/down(client/user) + var/mob/living/L = user.mob + L.default_toggle_sprint(TRUE) + return TRUE + +/datum/keybinding/mob/toggle_move_intent + hotkey_keys = list("Alt") + name = "toggle_move_intent" + full_name = "Hold to toggle move intent" + description = "Held down to cycle to the other move intent, release to cycle back" + category = CATEGORY_MOVEMENT + +/datum/keybinding/mob/toggle_move_intent/down(client/user) + var/mob/M = user.mob + M.toggle_move_intent() + return TRUE + +/datum/keybinding/mob/toggle_move_intent/up(client/user) + var/mob/M = user.mob + M.toggle_move_intent() + return TRUE + +/datum/keybinding/mob/toggle_move_intent_alternative + hotkey_keys = list("Unbound") + name = "toggle_move_intent_alt" + full_name = "press to cycle move intent" + description = "Pressing this cycle to the opposite move intent, does not cycle back" + category = CATEGORY_MOVEMENT + +/datum/keybinding/mob/toggle_move_intent_alternative/down(client/user) + var/mob/M = user.mob + M.toggle_move_intent() + return TRUE diff --git a/code/modules/keybindings/keybind/robot.dm b/code/modules/keybindings/keybind/robot.dm new file mode 100644 index 0000000000..b9f6ce83eb --- /dev/null +++ b/code/modules/keybindings/keybind/robot.dm @@ -0,0 +1,61 @@ +/datum/keybinding/robot + category = CATEGORY_ROBOT + weight = WEIGHT_ROBOT + +/datum/keybinding/robot/can_use(client/user) + return iscyborg(user.mob) + +/datum/keybinding/robot/moduleone + hotkey_keys = list("1") + name = "module_one" + full_name = "Toggle module 1" + description = "Equips or unequips the first module" + +/datum/keybinding/robot/moduleone/down(client/user) + var/mob/living/silicon/robot/R = user.mob + R.toggle_module(1) + return TRUE + +/datum/keybinding/robot/moduletwo + hotkey_keys = list("2") + name = "module_two" + full_name = "Toggle module 2" + description = "Equips or unequips the second module" + +/datum/keybinding/robot/moduletwo/down(client/user) + var/mob/living/silicon/robot/R = user.mob + R.toggle_module(2) + return TRUE + +/datum/keybinding/robot/modulethree + hotkey_keys = list("3") + name = "module_three" + full_name = "Toggle module 3" + description = "Equips or unequips the third module" + +/datum/keybinding/robot/modulethree/down(client/user) + var/mob/living/silicon/robot/R = user.mob + R.toggle_module(3) + return TRUE + +/datum/keybinding/robot/intent_cycle + hotkey_keys = list("4") + name = "cycle_intent" + full_name = "Cycle intent left" + description = "Cycles the intent left" + +/datum/keybinding/robot/intent_cycle/down(client/user) + var/mob/living/silicon/robot/R = user.mob + R.a_intent_change(INTENT_HOTKEY_LEFT) + return TRUE + +/datum/keybinding/robot/unequip_module + hotkey_keys = list("Q") + name = "unequip_module" + full_name = "Unequip module" + description = "Unequips the active module" + +/datum/keybinding/robot/unequip_module/down(client/user) + var/mob/living/silicon/robot/R = user.mob + R.uneq_active() + return TRUE diff --git a/code/modules/keybindings/keybind/targeting.dm b/code/modules/keybindings/keybind/targeting.dm new file mode 100644 index 0000000000..1548d768cf --- /dev/null +++ b/code/modules/keybindings/keybind/targeting.dm @@ -0,0 +1,76 @@ +/datum/keybinding/mob/target_head_cycle + hotkey_keys = list("Numpad8") + name = "target_head_cycle" + full_name = "Target: Cycle head" + description = "" + category = CATEGORY_TARGETING + +/datum/keybinding/mob/target_head_cycle/down(client/user) + user.body_toggle_head() + return TRUE + +/datum/keybinding/mob/target_r_arm + hotkey_keys = list("Numpad4") + name = "target_r_arm" + full_name = "Target: right arm" + description = "" + category = CATEGORY_TARGETING + +/datum/keybinding/mob/target_r_arm/down(client/user) + user.body_r_arm() + return TRUE + +/datum/keybinding/mob/target_body_chest + hotkey_keys = list("Numpad5") + name = "target_body_chest" + full_name = "Target: Body" + description = "" + category = CATEGORY_TARGETING + +/datum/keybinding/mob/target_body_chest/down(client/user) + user.body_chest() + return TRUE + +/datum/keybinding/mob/target_left_arm + hotkey_keys = list("Numpad6") + name = "target_left_arm" + full_name = "Target: left arm" + description = "" + category = CATEGORY_TARGETING + +/datum/keybinding/mob/target_left_arm/down(client/user) + user.body_l_arm() + return TRUE + +/datum/keybinding/mob/target_right_leg + hotkey_keys = list("Numpad1") + name = "target_right_leg" + full_name = "Target: Right leg" + description = "" + category = CATEGORY_TARGETING + +/datum/keybinding/mob/target_right_leg/down(client/user) + user.body_r_leg() + return TRUE + +/datum/keybinding/mob/target_body_groin + hotkey_keys = list("Numpad2") + name = "target_body_groin" + full_name = "Target: Groin" + description = "" + category = CATEGORY_TARGETING + +/datum/keybinding/mob/target_body_groin/down(client/user) + user.body_groin() + return TRUE + +/datum/keybinding/mob/target_left_leg + hotkey_keys = list("Numpad3") + name = "target_left_leg" + full_name = "Target: left leg" + description = "" + category = CATEGORY_TARGETING + +/datum/keybinding/mob/target_left_leg/down(client/user) + user.body_l_leg() + return TRUE diff --git a/code/modules/keybindings/setup.dm b/code/modules/keybindings/setup.dm index 9a13bfb11c..a53820b5d2 100644 --- a/code/modules/keybindings/setup.dm +++ b/code/modules/keybindings/setup.dm @@ -1,55 +1,47 @@ -/client - /// Keys currently held - var/list/keys_held = list() - /// These next two vars are to apply movement for keypresses and releases made while move delayed. - /// Because discarding that input makes the game less responsive. - /// On next move, add this dir to the move that would otherwise be done - var/next_move_dir_add - /// On next move, subtract this dir from the move that would otherwise be done - var/next_move_dir_sub - -// Set a client's focus to an object and override these procs on that object to let it handle keypresses - /datum/proc/key_down(key, client/user) // Called when a key is pressed down initially return + /datum/proc/key_up(key, client/user) // Called when a key is released return + /datum/proc/keyLoop(client/user) // Called once every frame set waitfor = FALSE return // removes all the existing macros /client/proc/erase_all_macros() - var/list/macro_sets = params2list(winget(src, null, "macros")) var/erase_output = "" - for(var/i in 1 to macro_sets.len) - var/setname = macro_sets[i] - var/list/macro_set = params2list(winget(src, "[setname].*", "command")) // The third arg doesnt matter here as we're just removing them all - for(var/k in 1 to macro_set.len) - var/list/split_name = splittext(macro_set[k], ".") - var/macro_name = "[split_name[1]].[split_name[2]]" // [3] is "command" - erase_output = "[erase_output];[macro_name].parent=null" + var/list/macro_set = params2list(winget(src, "default.*", "command")) // The third arg doesnt matter here as we're just removing them all + for(var/k in 1 to length(macro_set)) + var/list/split_name = splittext(macro_set[k], ".") + var/macro_name = "[split_name[1]].[split_name[2]]" // [3] is "command" + erase_output = "[erase_output];[macro_name].parent=null" winset(src, null, erase_output) -/client/proc/set_macros() +/client/proc/apply_macro_set(name, list/macroset) + ASSERT(name) + ASSERT(islist(macroset)) + winclone(src, "default", name) + for(var/i in 1 to length(macroset)) + var/key = macroset[i] + var/command = macroset[key] + winset(src, "[name]-[REF(key)]", "parent=[name];name=[key];command=[command]") + +/client/proc/set_macros(datum/preferences/prefs_override = prefs) set waitfor = FALSE keys_held.Cut() erase_all_macros() - var/list/macro_sets = SSinput.macro_sets - for(var/i in 1 to macro_sets.len) - var/setname = macro_sets[i] - if(setname != "default") - winclone(src, "default", setname) - var/list/macro_set = macro_sets[setname] - for(var/k in 1 to macro_set.len) - var/key = macro_set[k] - var/command = macro_set[key] - winset(src, "[setname]-[REF(key)]", "parent=[setname];name=[key];command=[command]") + apply_macro_set(SKIN_MACROSET_HOTKEYS, SSinput.macroset_hotkey) + apply_macro_set(SKIN_MACROSET_CLASSIC_HOTKEYS, SSinput.macroset_classic_hotkey) + apply_macro_set(SKIN_MACROSET_CLASSIC_INPUT, SSinput.macroset_classic_input) - if(prefs.hotkeys) - winset(src, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED] mainwindow.macro=default") + set_hotkeys_preference() + +/client/proc/set_hotkeys_preference(datum/preferences/prefs_override = prefs) + if(prefs_override.hotkeys) + winset(src, null, "map.focus=true input.background-color=[COLOR_INPUT_DISABLED] mainwindow.macro=[SKIN_MACROSET_HOTKEYS]") else - winset(src, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED] mainwindow.macro=old_default") + winset(src, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED] mainwindow.macro=[SKIN_MACROSET_CLASSIC_INPUT]") diff --git a/code/modules/language/codespeak.dm b/code/modules/language/codespeak.dm index be325d14b0..5d658b1fce 100644 --- a/code/modules/language/codespeak.dm +++ b/code/modules/language/codespeak.dm @@ -46,7 +46,7 @@ return to_chat(user, "You start skimming through [src], and suddenly your mind is filled with codewords and responses.") - user.grant_language(/datum/language/codespeak) + user.grant_language(/datum/language/codespeak, TRUE, TRUE, LANGUAGE_MIND) use_charge(user) @@ -65,7 +65,7 @@ M.visible_message("[user] beats [M] over the head with [src]!", "[user] beats you over the head with [src]!", "You hear smacking.") else M.visible_message("[user] teaches [M] by beating [M.p_them()] over the head with [src]!", "As [user] hits you with [src], codewords and responses flow through your mind.", "You hear smacking.") - M.grant_language(/datum/language/codespeak) + M.grant_language(/datum/language/codespeak, TRUE, TRUE, LANGUAGE_MIND) use_charge(user) /obj/item/codespeak_manual/proc/use_charge(mob/user) diff --git a/code/modules/language/language_holder.dm b/code/modules/language/language_holder.dm index f31ea9022b..6e3d27f2b8 100644 --- a/code/modules/language/language_holder.dm +++ b/code/modules/language/language_holder.dm @@ -1,149 +1,332 @@ -/datum/language_holder - var/list/languages = list(/datum/language/common) - var/list/shadow_languages = list() - var/only_speaks_language = null - var/selected_default_language = null - var/datum/language_menu/language_menu +/*!Language holders will either exist in an atom/movable or a mind. Creation of language holders happens +automatically when they are needed, for example when something tries to speak. +Where a mind is available, the mind language holder will be the one "in charge". The mind holder +will update its languages based on the atom holder, and will get updated as part of +transformations and other events that cause new languages to become available. +Every language holder has three lists of languages (and sources for each of them): +- understood_languages +- spoken_languages +- blocked_languages +Understood languages let you understand them, spoken languages lets you speak them +(if your tongue is compatible), and blocked languages will let you do neither no matter +what the source of the language is. +Language holders are designed to mostly only ever require the use the helpers in atom/movable +to achieve your goals, but it is also possible to work on them directly if needed. Any adding +and removing of languages and sources should only happen through the procs, as directly changing +these will mess something up somewhere down the line. +All atom movables have the initial_language_holder var which allows you to set the default language +holder to create. For example, /datum/language_holder/alien will give you xenocommon and a block for +galactic common. Human species also have a default language holder var that will be updated on +species change, initial_species_holder. +Key procs +* [grant_language](atom/movable.html#proc/grant_language) +* [remove_language](atom/movable.html#proc/remove_language) +* [add_blocked_language](atom/movable.html#proc/add_blocked_language) +* [remove_blocked_language](atom/movable.html#proc/remove_blocked_language) +* [grant_all_languages](atom/movable.html#proc/grant_all_languages) +* [remove_all_languages](atom/movable.html#proc/remove_all_languages) +* [has_language](atom/movable.html#proc/has_language) +* [can_speak_language](atom/movable.html#proc/can_speak_language) +* [get_selected_language](atom/movable.html#proc/get_selected_language) +* [update_atom_languages](atom/movable.html#proc/update_atom_languages) +*/ +/datum/language_holder + /// Understood languages. + var/list/understood_languages = list(/datum/language/common = list(LANGUAGE_MIND)) + /// A list of languages that can be spoken. Tongue organ may also set limits beyond this list. + var/list/spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM)) + /// A list of blocked languages. Used to prevent understanding and speaking certain languages, ie for certain mobs, mutations etc. + var/list/blocked_languages = list() + /// If true, overrides tongue limitations. var/omnitongue = FALSE + /// Handles displaying the language menu UI. + var/datum/language_menu/language_menu + /// Currently spoken language + var/selected_language + /// Tracks the entity that owns the holder. var/owner -/datum/language_holder/New(owner) - src.owner = owner - - languages = typecacheof(languages) - shadow_languages = typecacheof(shadow_languages) - -/datum/language_holder/Destroy() - owner = null - QDEL_NULL(language_menu) - languages.Cut() - shadow_languages.Cut() - return ..() - -/datum/language_holder/proc/copy(newowner) - var/datum/language_holder/copy = new(newowner) - copy.languages = src.languages.Copy() - // shadow languages are not copied. - copy.only_speaks_language = src.only_speaks_language - copy.selected_default_language = src.selected_default_language - // language menu is not copied, that's tied to the holder. - copy.omnitongue = src.omnitongue - return copy - -/datum/language_holder/proc/grant_language(datum/language/dt, shadow = FALSE) - if(shadow) - shadow_languages[dt] = TRUE - else - languages[dt] = TRUE - -/datum/language_holder/proc/grant_all_languages(omnitongue=FALSE) - for(var/la in GLOB.all_languages) - grant_language(la) - - if(omnitongue) - src.omnitongue = TRUE - -/datum/language_holder/proc/get_random_understood_language() - var/list/possible = list() - for(var/dt in languages) - possible += dt - . = safepick(possible) - -/datum/language_holder/proc/remove_language(datum/language/dt, shadow = FALSE) - if(shadow) - shadow_languages -= dt - else - languages -= dt - -/datum/language_holder/proc/remove_all_languages() - languages.Cut() - -/datum/language_holder/proc/has_language(datum/language/dt) - if(is_type_in_typecache(dt, languages)) - return LANGUAGE_KNOWN - else - var/atom/movable/AM = get_atom() - var/datum/language_holder/L = AM.get_language_holder(shadow=FALSE) - if(L != src) - if(is_type_in_typecache(dt, L.shadow_languages)) - return LANGUAGE_SHADOWED - return FALSE - -/datum/language_holder/proc/copy_known_languages_from(thing, replace=FALSE) - var/datum/language_holder/other - if(istype(thing, /datum/language_holder)) - other = thing - else if(ismovable(thing)) - var/atom/movable/AM = thing - other = AM.get_language_holder() - else if(istype(thing, /datum/mind)) - var/datum/mind/M = thing - other = M.get_language_holder() - - if(replace) - src.remove_all_languages() - - for(var/l in other.languages) - src.grant_language(l) - - -/datum/language_holder/proc/open_language_menu(mob/user) - if(!language_menu) - language_menu = new(src) - language_menu.ui_interact(user) - -/datum/language_holder/proc/get_atom() - if(ismovable(owner)) - . = owner - else if(istype(owner, /datum/mind)) +/// Initializes, and copies in the languages from the current atom if available. +/datum/language_holder/New(_owner) + owner = _owner + if(istype(owner, /datum/mind)) var/datum/mind/M = owner if(M.current) - . = M.current + update_atom_languages(M.current) + get_selected_language() + +/datum/language_holder/Destroy() + QDEL_NULL(language_menu) + return ..() + +/// Grants the supplied language. +/datum/language_holder/proc/grant_language(language, understood = TRUE, spoken = TRUE, source = LANGUAGE_MIND) + if(understood) + if(!understood_languages[language]) + understood_languages[language] = list() + understood_languages[language] |= source + . = TRUE + if(spoken) + if(!spoken_languages[language]) + spoken_languages[language] = list() + spoken_languages[language] |= source + . = TRUE + +/// Grants every language to understood and spoken, and gives omnitongue. +/datum/language_holder/proc/grant_all_languages(understood = TRUE, spoken = TRUE, grant_omnitongue = TRUE, source = LANGUAGE_MIND) + for(var/language in GLOB.all_languages) + grant_language(language, understood, spoken, source) + if(grant_omnitongue) // Overrides tongue limitations. + omnitongue = TRUE + return TRUE + +/// Removes a single language or source, removing all sources returns the pre-removal state of the language. +/datum/language_holder/proc/remove_language(language, understood = TRUE, spoken = TRUE, source = LANGUAGE_ALL) + if(understood && understood_languages[language]) + if(source == LANGUAGE_ALL) + understood_languages -= language + else + understood_languages[language] -= source + if(!length(understood_languages[language])) + understood_languages -= language + . = TRUE + + if(spoken && spoken_languages[language]) + if(source == LANGUAGE_ALL) + spoken_languages -= language + else + spoken_languages[language] -= source + if(!length(spoken_languages[language])) + spoken_languages -= language + . = TRUE + +/// Removes every language and optionally sets omnitongue false. If a non default source is supplied, only removes that source. +/datum/language_holder/proc/remove_all_languages(source = LANGUAGE_ALL, remove_omnitongue = FALSE) + for(var/language in GLOB.all_languages) + remove_language(language, TRUE, TRUE, source) + if(remove_omnitongue) + omnitongue = FALSE + return TRUE + +/// Adds a single language or list of languages to the blocked language list. +/datum/language_holder/proc/add_blocked_language(languages, source = LANGUAGE_MIND) + if(!islist(languages)) + languages = list(languages) + for(var/language in languages) + if(!blocked_languages[language]) + blocked_languages[language] = list() + blocked_languages[language] |= source + return TRUE + +/// Removes a single language or list of languages from the blocked language list. +/datum/language_holder/proc/remove_blocked_language(languages, source = LANGUAGE_MIND) + if(!islist(languages)) + languages = list(languages) + for(var/language in languages) + if(blocked_languages[language]) + if(source == LANGUAGE_ALL) + blocked_languages -= language + else + blocked_languages[language] -= source + if(!length(blocked_languages[language])) + blocked_languages -= language + return TRUE + +/// Checks if you have the language. If spoken is true, only checks if you can speak the language. +/datum/language_holder/proc/has_language(language, spoken = FALSE) + if(language in blocked_languages) + return FALSE + if(spoken) + return language in spoken_languages + return language in understood_languages + +/// Checks if you can speak the language. Tongue limitations should be supplied as an argument. +/datum/language_holder/proc/can_speak_language(language) + var/atom/movable/ouratom = get_atom() + var/tongue = ouratom.could_speak_language(language) + if((omnitongue || tongue) && has_language(language, TRUE)) + return TRUE + return FALSE + +/// Returns selected language if it can be spoken, or decides, sets and returns a new selected language if possible. +/datum/language_holder/proc/get_selected_language() + if(selected_language && can_speak_language(selected_language)) + return selected_language + selected_language = null + var/highest_priority + for(var/lang in spoken_languages) + var/datum/language/language = lang + var/priority = initial(language.default_priority) + if((!highest_priority || (priority > highest_priority)) && !(language in blocked_languages)) + if(can_speak_language(language)) + selected_language = language + highest_priority = priority + return selected_language + +/// Gets a random understood language, useful for hallucinations and such. +/datum/language_holder/proc/get_random_understood_language() + return pick(understood_languages) + +/// Gets a random spoken language, useful for forced speech and such. +/datum/language_holder/proc/get_random_spoken_language() + return pick(spoken_languages) + +/// Opens a language menu reading from the language holder. +/datum/language_holder/proc/open_language_menu(mob/user) + if(!language_menu) + language_menu = new (src) + language_menu.ui_interact(user) + +/// Gets the atom, since we some times need to check if the tongue has limitations. +/datum/language_holder/proc/get_atom() + if(owner) + if(istype(owner, /datum/mind)) + var/datum/mind/M = owner + return M.current + return owner + return FALSE + +/// Empties out the atom specific languages and updates them according to the supplied atoms language holder. +/datum/language_holder/proc/update_atom_languages(atom/movable/thing) + var/datum/language_holder/from_atom = thing.get_language_holder(FALSE) //Gets the atoms language holder + if(from_atom == src) //This could happen if called on an atom without a mind. + return FALSE + for(var/language in understood_languages) + remove_language(language, TRUE, FALSE, LANGUAGE_ATOM) + for(var/language in spoken_languages) + remove_language(language, FALSE, TRUE, LANGUAGE_ATOM) + for(var/language in blocked_languages) + remove_blocked_language(language, LANGUAGE_ATOM) + + copy_languages(from_atom) + get_selected_language() + return TRUE + +/// Copies all languages from the supplied atom/language holder. Source should be overridden when you +/// do not want the language overwritten by later atom updates or want to avoid blocked languages. +/datum/language_holder/proc/copy_languages(var/datum/language_holder/from_holder, source_override) + if(source_override) //No blocked languages here, for now only used by ling absorb. + for(var/language in from_holder.understood_languages) + grant_language(language, TRUE, FALSE, source_override) + for(var/language in from_holder.spoken_languages) + grant_language(language, FALSE, TRUE, source_override) + else + for(var/language in from_holder.understood_languages) + grant_language(language, TRUE, FALSE, from_holder.understood_languages[language]) + for(var/language in from_holder.spoken_languages) + grant_language(language, FALSE, TRUE, from_holder.spoken_languages[language]) + for(var/language in from_holder.blocked_languages) + add_blocked_language(language, from_holder.blocked_languages[language]) + return TRUE + + +//************************************************ +//* Specific language holders * +//* Use atom language sources only. * +//************************************************/ + /datum/language_holder/alien - languages = list(/datum/language/xenocommon) - -/datum/language_holder/monkey - languages = list(/datum/language/monkey) - -/datum/language_holder/swarmer - languages = list(/datum/language/swarmer) + understood_languages = list(/datum/language/xenocommon = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/xenocommon = list(LANGUAGE_ATOM)) + blocked_languages = list(/datum/language/common = list(LANGUAGE_ATOM)) /datum/language_holder/clockmob - languages = list(/datum/language/common, /datum/language/ratvar) - only_speaks_language = /datum/language/ratvar + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/ratvar = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/ratvar = list(LANGUAGE_ATOM)) /datum/language_holder/construct - languages = list(/datum/language/common, /datum/language/narsie) + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/narsie = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/narsie = list(LANGUAGE_ATOM)) /datum/language_holder/drone - languages = list(/datum/language/common, /datum/language/drone, /datum/language/machine) - only_speaks_language = /datum/language/drone + understood_languages = list(/datum/language/drone = list(LANGUAGE_ATOM), + /datum/language/machine = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/drone = list(LANGUAGE_ATOM)) + blocked_languages = list(/datum/language/common = list(LANGUAGE_ATOM)) /datum/language_holder/drone/syndicate - only_speaks_language = null + blocked_languages = null /datum/language_holder/dwarf - languages = list(/datum/language/common, /datum/language/dwarf) - only_speaks_language = /datum/language/dwarf + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/dwarf = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/dwarf = list(LANGUAGE_ATOM)) -/datum/language_holder/slime - languages = list(/datum/language/common, /datum/language/slime) - only_speaks_language = /datum/language/slime +/datum/language_holder/jelly + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/slime = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/slime = list(LANGUAGE_ATOM)) /datum/language_holder/lightbringer - // TODO change to a lightbringer specific sign language - languages = list(/datum/language/slime) + understood_languages = list(/datum/language/slime = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/slime = list(LANGUAGE_ATOM)) + blocked_languages = list(/datum/language/common = list(LANGUAGE_ATOM)) + +/datum/language_holder/lizard + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/draconic = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/draconic = list(LANGUAGE_ATOM)) + +/datum/language_holder/lizard/ash + selected_language = /datum/language/draconic + +/datum/language_holder/monkey + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/monkey = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/monkey = list(LANGUAGE_ATOM)) + +/datum/language_holder/mushroom + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/mushroom = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/mushroom = list(LANGUAGE_ATOM)) + +/datum/language_holder/slime + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/slime = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/slime = list(LANGUAGE_ATOM)) + +/datum/language_holder/swarmer + understood_languages = list(/datum/language/swarmer = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/swarmer = list(LANGUAGE_ATOM)) + blocked_languages = list(/datum/language/common = list(LANGUAGE_ATOM)) + +/datum/language_holder/sylvan + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/sylvan = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/sylvan = list(LANGUAGE_ATOM)) + /datum/language_holder/synthetic - languages = list(/datum/language/common) - shadow_languages = list(/datum/language/common, /datum/language/machine, /datum/language/draconic, /datum/language/slime, /datum/language/dwarf) + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/machine = list(LANGUAGE_ATOM), + /datum/language/draconic = list(LANGUAGE_ATOM), + /datum/language/slime = list(LANGUAGE_ATOM), + /datum/language/dwarf = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/machine = list(LANGUAGE_ATOM), + /datum/language/draconic = list(LANGUAGE_ATOM), + /datum/language/slime = list(LANGUAGE_ATOM), + /datum/language/dwarf = list(LANGUAGE_ATOM)) + +/datum/language_holder/venus + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/sylvan = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/sylvan = list(LANGUAGE_ATOM)) /datum/language_holder/empty - languages = list() - shadow_languages = list() + understood_languages = list() + spoken_languages = list() /datum/language_holder/universal/New() ..() - grant_all_languages(omnitongue=TRUE) + grant_all_languages() diff --git a/code/modules/language/language_menu.dm b/code/modules/language/language_menu.dm index eea87f1d80..a7ce211a18 100644 --- a/code/modules/language/language_menu.dm +++ b/code/modules/language/language_menu.dm @@ -1,8 +1,8 @@ /datum/language_menu var/datum/language_holder/language_holder -/datum/language_menu/New(language_holder) - src.language_holder = language_holder +/datum/language_menu/New(_language_holder) + language_holder = _language_holder /datum/language_menu/Destroy() language_holder = null @@ -24,21 +24,20 @@ data["is_living"] = FALSE data["languages"] = list() - for(var/ld in GLOB.all_languages) - var/result = language_holder.has_language(ld) + for(var/lang in GLOB.all_languages) + var/result = language_holder.has_language(lang) || language_holder.has_language(lang, TRUE) if(!result) continue - var/shadow = result == LANGUAGE_SHADOWED - var/datum/language/LD = ld + var/datum/language/language = lang var/list/L = list() - L["name"] = initial(LD.name) - L["desc"] = initial(LD.desc) - L["key"] = initial(LD.key) - L["is_default"] = (LD == language_holder.selected_default_language) - L["shadow"] = shadow + L["name"] = initial(language.name) + L["desc"] = initial(language.desc) + L["key"] = initial(language.key) + L["is_default"] = (language == language_holder.selected_language) if(AM) - L["can_speak"] = AM.can_speak_in_language(LD) + L["can_speak"] = AM.can_speak_language(language) + L["can_understand"] = AM.has_language(language) data["languages"] += list(L) @@ -47,15 +46,15 @@ data["omnitongue"] = language_holder.omnitongue data["unknown_languages"] = list() - for(var/ld in GLOB.all_languages) - if(language_holder.has_language(ld)) + for(var/lang in GLOB.all_languages) + if(language_holder.has_language(lang) || language_holder.has_language(lang, TRUE)) continue - var/datum/language/LD = ld + var/datum/language/language = lang var/list/L = list() - L["name"] = initial(LD.name) - L["desc"] = initial(LD.desc) - L["key"] = initial(LD.key) + L["name"] = initial(language.name) + L["desc"] = initial(language.desc) + L["key"] = initial(language.key) data["unknown_languages"] += list(L) return data @@ -68,27 +67,51 @@ var/language_name = params["language_name"] var/datum/language/language_datum - for(var/ld in GLOB.all_languages) - var/datum/language/LD = ld - if(language_name == initial(LD.name)) - language_datum = LD + for(var/lang in GLOB.all_languages) + var/datum/language/language = lang + if(language_name == initial(language.name)) + language_datum = language var/is_admin = check_rights_for(user.client, R_ADMIN) switch(action) if("select_default") - if(language_datum && AM.can_speak_in_language(language_datum)) - language_holder.selected_default_language = language_datum + if(language_datum && AM.can_speak_language(language_datum)) + language_holder.selected_language = language_datum . = TRUE if("grant_language") if((is_admin || isobserver(AM)) && language_datum) - language_holder.grant_language(language_datum) + var/list/choices = list("Only Spoken", "Only Understood", "Both") + var/choice = input(user,"How do you want to add this language?","[language_datum]",null) as null|anything in choices + var/spoken = FALSE + var/understood = FALSE + switch(choice) + if("Only Spoken") + spoken = TRUE + if("Only Understood") + understood = TRUE + if("Both") + spoken = TRUE + understood = TRUE + language_holder.grant_language(language_datum, understood, spoken) if(is_admin) message_admins("[key_name_admin(user)] granted the [language_name] language to [key_name_admin(AM)].") log_admin("[key_name(user)] granted the language [language_name] to [key_name(AM)].") . = TRUE if("remove_language") if((is_admin || isobserver(AM)) && language_datum) - language_holder.remove_language(language_datum) + var/list/choices = list("Only Spoken", "Only Understood", "Both") + var/choice = input(user,"Which part do you wish to remove?","[language_datum]",null) as null|anything in choices + var/spoken = FALSE + var/understood = FALSE + switch(choice) + if("Only Spoken") + spoken = TRUE + if("Only Understood") + understood = TRUE + if("Both") + spoken = TRUE + understood = TRUE + language_holder.remove_language(language_datum, understood, spoken) if(is_admin) message_admins("[key_name_admin(user)] removed the [language_name] language to [key_name_admin(AM)].") log_admin("[key_name(user)] removed the language [language_name] to [key_name(AM)].") diff --git a/modular_citadel/code/modules/language/sylvan.dm b/code/modules/language/sylvan.dm similarity index 76% rename from modular_citadel/code/modules/language/sylvan.dm rename to code/modules/language/sylvan.dm index c9458bb4cf..3bbf5f6afd 100644 --- a/modular_citadel/code/modules/language/sylvan.dm +++ b/code/modules/language/sylvan.dm @@ -14,10 +14,5 @@ "incas", "int", "elc", "ent", "aws", "qip", "nas", "vil", "jens", "dila", "fa", "la", "re", "do", "ji", "ae", "so", "qe", "ce", "na", "mo", "ha", "yu" ) - icon = 'icons/obj/hydroponics/harvest.dmi' - icon_state = "lily" + icon_state = "plant" default_priority = 90 - -/datum/language_holder/venus - languages = list(/datum/language/common, /datum/language/sylvan, /datum/language/machine) - only_speaks_language = /datum/language/sylvan diff --git a/code/modules/lighting/lighting_corner.dm b/code/modules/lighting/lighting_corner.dm index d4530acd04..c6e363be07 100644 --- a/code/modules/lighting/lighting_corner.dm +++ b/code/modules/lighting/lighting_corner.dm @@ -2,11 +2,11 @@ // And corners get shared between multiple turfs (unless you're on the corners of the map, then 1 corner doesn't). // For the record: these should never ever ever be deleted, even if the turf doesn't have dynamic lighting. -// This list is what the code that assigns corners listens to, the order in this list is the order in which corners are added to the /turf/corners list. -GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, NORTHWEST)) - /datum/lighting_corner - var/list/turf/masters + var/turf/northeast + var/turf/northwest + var/turf/southeast + var/turf/southwest var/list/datum/light_source/affecting // Light sources affecting us. var/active = FALSE // TRUE if one of our masters has dynamic lighting. @@ -25,10 +25,18 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, var/cache_b = LIGHTING_SOFT_THRESHOLD var/cache_mx = 0 -/datum/lighting_corner/New(var/turf/new_turf, var/diagonal) +// Diagonal is our direction FROM them, not to. +/datum/lighting_corner/New(turf/new_turf, diagonal) . = ..() - masters = list() - masters[new_turf] = turn(diagonal, 180) + +#define SET_DIAGONAL(turf, diagonal) \ + switch(diagonal){ \ + if(SOUTHWEST) { northeast = turf; turf.lc_bottomleft = src; } \ + if(SOUTHEAST) { northwest = turf; turf.lc_bottomright = src; } \ + if(NORTHEAST) { southwest = turf; turf.lc_topright = src; } \ + if(NORTHWEST) { southeast = turf; turf.lc_topleft = src; } \ + } + SET_DIAGONAL(new_turf, diagonal) z = new_turf.z var/vertical = diagonal & ~(diagonal - 1) // The horizontal directions (4 and 8) are bigger than the vertical ones (1 and 2), so we can reliably say the lsb is the horizontal direction. @@ -37,52 +45,28 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, x = new_turf.x + (horizontal == EAST ? 0.5 : -0.5) y = new_turf.y + (vertical == NORTH ? 0.5 : -0.5) - // My initial plan was to make this loop through a list of all the dirs (horizontal, vertical, diagonal). - // Issue being that the only way I could think of doing it was very messy, slow and honestly overengineered. - // So we'll have this hardcode instead. var/turf/T - var/i - - // Diagonal one is easy. + // Build diagonal one T = get_step(new_turf, diagonal) - if (T) // In case we're on the map's border. - if (!T.corners) - T.corners = list(null, null, null, null) - - masters[T] = diagonal - i = GLOB.LIGHTING_CORNER_DIAGONAL.Find(turn(diagonal, 180)) - T.corners[i] = src - - // Now the horizontal one. + if(T) + SET_DIAGONAL(T, turn(diagonal, 180)) + // Build horizontal T = get_step(new_turf, horizontal) - if (T) // Ditto. - if (!T.corners) - T.corners = list(null, null, null, null) - - masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates. - i = GLOB.LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180)) - T.corners[i] = src - - // And finally the vertical one. + if(T) + SET_DIAGONAL(T, turn(((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH), 180)) + // Build vertical T = get_step(new_turf, vertical) - if (T) - if (!T.corners) - T.corners = list(null, null, null, null) - - masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates. - i = GLOB.LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180)) - T.corners[i] = src + if(T) + SET_DIAGONAL(T, turn(((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH), 180)) update_active() +#undef SET_DIAGONAL + /datum/lighting_corner/proc/update_active() active = FALSE - var/turf/T - var/thing - for (thing in masters) - T = thing - if (T.lighting_object) - active = TRUE + if(northeast?.lighting_object || northwest?.lighting_object || southeast?.lighting_object || southwest?.lighting_object) + active = TRUE // God that was a mess, now to do the rest of the corner code! Hooray! /datum/lighting_corner/proc/update_lumcount(var/delta_r, var/delta_g, var/delta_b) @@ -122,13 +106,12 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, #endif cache_mx = round(mx, LIGHTING_ROUND_VALUE) - for (var/TT in masters) - var/turf/T = TT - if (T.lighting_object) - if (!T.lighting_object.needs_update) - T.lighting_object.needs_update = TRUE - GLOB.lighting_update_objects += T.lighting_object - + #define QUEUE(turf) if(turf?.lighting_object && !turf.lighting_object.needs_update) { turf.lighting_object.needs_update = TRUE; GLOB.lighting_update_objects += turf.lighting_object } + QUEUE(northeast) + QUEUE(northwest) + QUEUE(southeast) + QUEUE(southwest) + #undef QUEUE /datum/lighting_corner/dummy/New() return diff --git a/code/modules/lighting/lighting_object.dm b/code/modules/lighting/lighting_object.dm index 9ceb341f91..ffa2d86e15 100644 --- a/code/modules/lighting/lighting_object.dm +++ b/code/modules/lighting/lighting_object.dm @@ -55,7 +55,7 @@ if (loc) var/turf/oldturf = get_turf(myturf) var/turf/newturf = get_turf(loc) - warning("A lighting object realised it's loc had changed in update() ([myturf]\[[myturf ? myturf.type : "null"]]([COORD(oldturf)]) -> [loc]\[[ loc ? loc.type : "null"]]([COORD(newturf)]))!") + stack_trace("A lighting object realised it's loc had changed in update() ([myturf]\[[myturf ? myturf.type : "null"]]([COORD(oldturf)]) -> [loc]\[[ loc ? loc.type : "null"]]([COORD(newturf)]))!") qdel(src, TRUE) return @@ -71,16 +71,10 @@ // See LIGHTING_CORNER_DIAGONAL in lighting_corner.dm for why these values are what they are. var/static/datum/lighting_corner/dummy/dummy_lighting_corner = new - var/list/corners = myturf.corners - var/datum/lighting_corner/cr = dummy_lighting_corner - var/datum/lighting_corner/cg = dummy_lighting_corner - var/datum/lighting_corner/cb = dummy_lighting_corner - var/datum/lighting_corner/ca = dummy_lighting_corner - if (corners) //done this way for speed - cr = corners[3] || dummy_lighting_corner - cg = corners[2] || dummy_lighting_corner - cb = corners[4] || dummy_lighting_corner - ca = corners[1] || dummy_lighting_corner + var/datum/lighting_corner/cr = myturf.lc_bottomleft || dummy_lighting_corner + var/datum/lighting_corner/cg = myturf.lc_bottomright || dummy_lighting_corner + var/datum/lighting_corner/cb = myturf.lc_topleft || dummy_lighting_corner + var/datum/lighting_corner/ca = myturf.lc_topright || dummy_lighting_corner var/max = max(cr.cache_mx, cg.cache_mx, cb.cache_mx, ca.cache_mx) diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm index 6e48d0097c..d97967dff9 100644 --- a/code/modules/lighting/lighting_source.dm +++ b/code/modules/lighting/lighting_source.dm @@ -237,18 +237,25 @@ return //nothing's changed var/list/datum/lighting_corner/corners = list() + var/datum/lighting_corner/C var/list/turf/turfs = list() var/thing - var/datum/lighting_corner/C var/turf/T if (source_turf) var/oldlum = source_turf.luminosity source_turf.luminosity = CEILING(light_range, 1) for(T in view(CEILING(light_range, 1), source_turf)) - for (thing in T.get_corners(source_turf)) - C = thing - corners[C] = 0 turfs += T + if(!IS_DYNAMIC_LIGHTING(T) && !T.light_sources) + continue + if(!T.lighting_corners_initialised) + T.generate_missing_corners() + if(T.has_opaque_atom) + continue + corners[T.lc_topright] = 0 + corners[T.lc_bottomright] = 0 + corners[T.lc_bottomleft] = 0 + corners[T.lc_topleft] = 0 source_turf.luminosity = oldlum LAZYINITLIST(affecting_turfs) diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index fdd581a292..fc9cd0336d 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -6,9 +6,15 @@ var/tmp/list/datum/light_source/affecting_lights // List of light sources affecting this turf. var/tmp/atom/movable/lighting_object/lighting_object // Our lighting object. - var/tmp/list/datum/lighting_corner/corners + var/tmp/datum/lighting_corner/lc_topleft + var/tmp/datum/lighting_corner/lc_topright + var/tmp/datum/lighting_corner/lc_bottomleft + var/tmp/datum/lighting_corner/lc_bottomright var/tmp/has_opaque_atom = FALSE // Not to be confused with opacity, this will be TRUE if there's any opaque atom on the tile. +// counterclockwisse 0 to 360 +#define PROC_ON_CORNERS(operation) lc_topright?.##operation;lc_bottomright?.##operation;lc_bottomleft?.##operation;lc_topleft?.##operation + // Causes any affecting light sources to be queued for a visibility update, for example a door got opened. /turf/proc/reconsider_lights() var/datum/light_source/L @@ -21,13 +27,7 @@ if (lighting_object) qdel(lighting_object, TRUE) - var/datum/lighting_corner/C - var/thing - for (thing in corners) - if(!thing) - continue - C = thing - C.update_active() + PROC_ON_CORNERS(update_active()) // Builds a lighting object for us, but only if our area is dynamic. /turf/proc/lighting_build_overlay() @@ -43,32 +43,31 @@ new/atom/movable/lighting_object(src) - var/thing - var/datum/lighting_corner/C var/datum/light_source/S - for (thing in corners) - if(!thing) - continue - C = thing - if (!C.active) // We would activate the corner, calculate the lighting for it. - for (thing in C.affecting) - S = thing - S.recalc_corner(C) - C.active = TRUE + var/i +#define OPERATE(corner) \ + if(corner && !corner.active) { \ + for(i in corner.affecting) { \ + S = i ; \ + S.recalc_corner(corner) \ + } \ + corner.active = TRUE \ + } + OPERATE(lc_topright) + OPERATE(lc_bottomright) + OPERATE(lc_bottomleft) + OPERATE(lc_topleft) +#undef OPERATE // Used to get a scaled lumcount. /turf/proc/get_lumcount(var/minlum = 0, var/maxlum = 1) - if (!lighting_object) + if(!lighting_object) return 1 - var/totallums = 0 - var/thing - var/datum/lighting_corner/L - for (thing in corners) - if(!thing) - continue - L = thing - totallums += L.lum_r + L.lum_b + L.lum_g + var/totallums = (lc_topright? (lc_topright.lum_r + lc_topright.lum_g + lc_topright.lum_b) : 0) \ + + (lc_bottomright? (lc_bottomright.lum_r + lc_bottomright.lum_g + lc_bottomright.lum_b) : 0) \ + + (lc_bottomleft? (lc_bottomleft.lum_r + lc_bottomleft.lum_g + lc_bottomleft.lum_b) : 0) \ + + (lc_topleft? (lc_topleft.lum_r + lc_topleft.lum_g + lc_topleft.lum_b) : 0) totallums /= 12 // 4 corners, each with 3 channels, get the average. @@ -110,27 +109,18 @@ else lighting_clear_overlay() -/turf/proc/get_corners() - if (!IS_DYNAMIC_LIGHTING(src) && !light_sources) - return null - if (!lighting_corners_initialised) - generate_missing_corners() - if (has_opaque_atom) - return null // Since this proc gets used in a for loop, null won't be looped though. - - return corners - /turf/proc/generate_missing_corners() if (!IS_DYNAMIC_LIGHTING(src) && !light_sources) return lighting_corners_initialised = TRUE - if (!corners) - corners = list(null, null, null, null) - - for (var/i = 1 to 4) - if (corners[i]) // Already have a corner on this direction. - continue - - corners[i] = new/datum/lighting_corner(src, GLOB.LIGHTING_CORNER_DIAGONAL[i]) - + // counterclockwise from 0 to 360. + if(!lc_topright) + new /datum/lighting_corner(src, NORTHEAST) + if(!lc_bottomright) + new /datum/lighting_corner(src, SOUTHEAST) + if(!lc_bottomleft) + new /datum/lighting_corner(src, SOUTHWEST) + if(!lc_topleft) + new /datum/lighting_corner(src, NORTHWEST) +#undef PROC_ON_CORNERS diff --git a/code/modules/mapping/reader.dm b/code/modules/mapping/reader.dm index 2f9ab4112e..a792ee280f 100644 --- a/code/modules/mapping/reader.dm +++ b/code/modules/mapping/reader.dm @@ -1,6 +1,12 @@ /////////////////////////////////////////////////////////////// //SS13 Optimized Map loader ////////////////////////////////////////////////////////////// +/* + * Notes: + * This does NOT support map files where more than one Z is in each grid set, as defined in the file. + * MultiZ map files ARE supported (however very much discouraged), as long as each gridset only contains one z. + * This assumes that for the most part, map files are properly formed, either DMM or TGM standard formats. If you feed it bad data, expect to crash. + */ #define SPACE_KEY "space" /datum/grid_set @@ -9,6 +15,12 @@ var/zcrd var/gridLines +/datum/grid_set/proc/height(key_len) + return length(gridLines) + +/datum/grid_set/proc/width(key_len) + return gridLines[1] / key_len + /datum/parsed_map var/original_path var/key_len = 0 @@ -43,7 +55,7 @@ /// - `cropMap`: When true, the map will be cropped to fit the existing world dimensions (Optional). /// - `measureOnly`: When true, no changes will be made to the world (Optional). /// - `no_changeturf`: When true, [turf/AfterChange] won't be called on loaded turfs -/// - `x_lower`, `x_upper`, `y_lower`, `y_upper`: Coordinates (relative to the map) to crop to (Optional). +/// - `x_lower`, `x_upper`, `y_lower`, `y_upper`: Coordinates (relative to the game world) to crop to (Optional). /// - `placeOnTop`: Whether to use [turf/PlaceOnTop] rather than [turf/ChangeTurf] (Optional). /proc/load_map( dmm_file as file, @@ -60,25 +72,37 @@ placeOnTop = FALSE as num, orientation = SOUTH as num, annihilate_tiles = FALSE, - z_lower = -INFINITY as num, - z_upper = INFINITY as num + crop_relative_to_game_world = TRUE ) - var/datum/parsed_map/parsed = new(dmm_file, x_lower, x_upper, y_lower, y_upper, z_lower, z_upper, measureOnly) + var/datum/parsed_map/parsed = new(dmm_file, measureOnly = measureOnly) if(parsed.bounds && !measureOnly) parsed.load(x_offset, y_offset, z_offset, cropMap, no_changeturf, x_lower, x_upper, y_lower, y_upper, placeOnTop, orientation, annihilate_tiles) return parsed -/// Parse a map, possibly cropping it. -//WHY THE HECK DO WE EVEN SUPPORT NEGATIVE COORDINATES, ALL IT IS IS A WASTE OF TIME AND CPU!!!??? -//DO NOT USE THIS TO TRIM MAPS UNLESS STRICTLY NEEDED! IT IS EXTREMELY EXPENSIVE TO DO SO! +/** + * Parse a map, possibly cropping it. + * Do not use the crop function unless strictly necessary. + * WARNING: Crop function crops based on the tiles you'd see in the map editor. If you're planning to load it in in a different orientation later, you better have done the math. + * It's recommended that you do not crop using this at all. + */ /datum/parsed_map/New(tfile, x_lower = -INFINITY, x_upper = INFINITY, y_lower = -INFINITY, y_upper = INFINITY, z_lower = -INFINITY, z_upper = INFINITY, measureOnly = FALSE) + _parse(tfile, x_lower, x_upper, y_lower, y_upper, z_lower, z_upper, measureOnly) + +/datum/parsed_map/proc/_parse(tfile, x_lower, x_upper, y_lower, y_upper, z_lower, z_upper, measureOnly) + var/static/parsing = FALSE + UNTIL(!parsing) + // do not multithread this or bad things happen + parsing = TRUE + _do_parse(tfile, x_lower, x_upper, y_lower, y_upper, z_lower, z_upper, measureOnly) + parsing = FALSE + +/datum/parsed_map/proc/_do_parse(tfile, x_lower, x_upper, y_lower, y_upper, z_lower, z_upper, measureOnly) if(isfile(tfile)) original_path = "[tfile]" tfile = file2text(tfile) else if(isnull(tfile)) // create a new datum without loading a map return - bounds = parsed_bounds = list(1.#INF, 1.#INF, 1.#INF, -1.#INF, -1.#INF, -1.#INF) ASSERT(x_upper >= x_lower) ASSERT(y_upper >= y_lower) @@ -107,12 +131,13 @@ if(!key_len) CRASH("Coords before model definition in DMM") + // NOTE: We are assuming each coordset only contains one z. + var/curr_z = text2num(dmmRegex.group[5]) + if(curr_z < z_lower || curr_z > z_upper) + continue + var/curr_x = text2num(dmmRegex.group[3]) var/curr_y = text2num(dmmRegex.group[4]) - var/curr_z = text2num(dmmRegex.group[5]) - - if(curr_x < x_lower || curr_y < y_lower || curr_z < z_lower || curr_z > z_upper) - continue var/datum/grid_set/gridSet = new @@ -120,12 +145,6 @@ gridSet.ycrd = curr_y gridSet.zcrd = curr_z - bounds[MAP_MINX] = min(bounds[MAP_MINX], curr_x) //since down is up for y/gridlines, we now know the lower left corner. - bounds[MAP_MINY] = min(bounds[MAP_MINY], curr_y) - bounds[MAP_MINZ] = min(bounds[MAP_MINZ], curr_z) - - bounds[MAP_MAXZ] = max(bounds[MAP_MAXZ], curr_z) //we know max z now - var/list/gridLines = splittext(dmmRegex.group[6], "\n") gridSet.gridLines = gridLines @@ -134,31 +153,36 @@ if(leadingBlanks > 1) gridLines.Cut(1, leadingBlanks) // Remove all leading blank lines. - gridSets += gridSet - var/lines = length(gridLines) - if(lines) - if(gridLines[gridLines.len] == "") - gridLines.Cut(gridLines.len) // Remove only one blank line at the end. - var/right_length = y_upper - curr_y + 1 - if(lines > right_length) - gridLines.len = right_length //this can't be negative due to our ASSERTions above, hopefully. - - if(!gridLines.len) // Skip it if there's no content. + if(lines && gridLines[lines] == "") + // remove one trailing blank line + gridLines.len-- + lines-- + // y crop + var/right_length = y_upper - curr_y + 1 + if(lines > right_length) + lines = gridLines.len = right_length + if(!lines) // blank continue - //do not use curr_y after this point, ycrd has changed. use it before because local var. - gridSet.ycrd += gridLines.len - 1 // Start at the top and work down - bounds[MAP_MAXY] = max(bounds[MAP_MAXY], gridSet.ycrd) //we know max y now + var/width = length(gridLines[1]) / key_len + // x crop + var/right_width = x_upper - curr_x + 1 + if(width > right_width) + for(var/i in 1 to lines) + gridLines[i] = copytext(gridLines[i], 1, key_len * right_width) + + // during the actual load we're starting at the top and working our way down + gridSet.ycrd += lines - 1 - var/linelength = length(gridLines[1]) //yes it only samples the first line, this is why you use TGM instead of DMM! - var/xlength = linelength / key_len - - var/maxx = gridSet.xcrd + xlength - 1 - if(maxx > x_upper) - for(var/i in 1 to length(gridLines)) - gridLines[i] = copytext(gridLines[i], 1, key_len * (x_upper - curr_x + 1)) - bounds[MAP_MAXX] = max(bounds[MAP_MAXX], maxx) + // Safe to proceed, commit gridset to list and record coords. + gridSets += gridSet + bounds[MAP_MINX] = min(bounds[MAP_MINX], curr_x) + bounds[MAP_MAXX] = max(bounds[MAP_MAXX], curr_x + width - 1) + bounds[MAP_MINY] = min(bounds[MAP_MINY], curr_y) + bounds[MAP_MAXY] = max(bounds[MAP_MAXY], curr_y + lines - 1) + bounds[MAP_MINZ] = min(bounds[MAP_MINZ], curr_z) + bounds[MAP_MAXZ] = max(bounds[MAP_MAXZ], curr_z) CHECK_TICK // Indicate failure to parse any coordinates by nulling bounds @@ -172,7 +196,8 @@ /datum/parsed_map/Destroy() if(template_host && template_host.cached_map == src) template_host.cached_map = null - return ..() + . = ..() + return QDEL_HINT_HARDDEL_NOW /// Load the parsed map into the world. See [/proc/load_map] for arguments. /datum/parsed_map/proc/load(x_offset, y_offset, z_offset, cropMap, no_changeturf, x_lower, x_upper, y_lower, y_upper, placeOnTop, orientation, annihilate_tiles, datum/map_orientation_pattern/forced_pattern) @@ -197,6 +222,8 @@ var/yi = mode.yi var/turn_angle = round(SIMPLIFY_DEGREES(mode.turn_angle), 90) var/delta_swap = x_offset - y_offset + // less checks later + var/do_crop = x_lower > -INFINITY || x_upper < INFINITY || y_lower > -INFINITY || y_upper < INFINITY for(var/__I in gridSets) var/datum/grid_set/gridset = __I @@ -221,6 +248,8 @@ for(var/pos = 1 to (length(line) - key_len + 1) step key_len) var/placement_x = swap_xy? (actual_y + delta_swap) : actual_x var/placement_y = swap_xy? (actual_x - delta_swap) : actual_y + if(do_crop && ((placement_x < x_lower) || (placement_x > x_upper) || (placement_y < y_lower) || (placement_y > y_upper))) + continue if(placement_x > world.maxx) if(cropMap) actual_x += xi @@ -532,6 +561,7 @@ // fallback: string return text -/datum/parsed_map/Destroy() - ..() - return QDEL_HINT_HARDDEL_NOW +/datum/parsed_map/vv_edit_var(var_name, var_value) + if(var_name == NAMEOF(src, dmmRegex) || var_name == NAMEOF(src, trimQuotesRegex) || var_name == NAMEOF(src, trimRegex)) + return FALSE + return ..() diff --git a/code/modules/mining/equipment/explorer_gear.dm b/code/modules/mining/equipment/explorer_gear.dm index 30eed6c8f0..39f8e296af 100644 --- a/code/modules/mining/equipment/explorer_gear.dm +++ b/code/modules/mining/equipment/explorer_gear.dm @@ -16,7 +16,6 @@ resistance_flags = FIRE_PROOF mutantrace_variation = STYLE_DIGITIGRADE|STYLE_SNEK_TAURIC|STYLE_PAW_TAURIC - /obj/item/clothing/head/hooded/explorer name = "explorer hood" desc = "An armoured hood for exploring harsh environments." @@ -24,7 +23,9 @@ body_parts_covered = HEAD flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT + cold_protection = HEAD max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT + heat_protection = HEAD armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 50) resistance_flags = FIRE_PROOF @@ -49,7 +50,7 @@ visor_flags_inv = HIDEFACIALHAIR visor_flags_cover = MASKCOVERSMOUTH actions_types = list(/datum/action/item_action/adjust) - armor = list("melee" = 10, "bullet" = 5, "laser" = 5, "energy" = 5, "bomb" = 0, "bio" = 50, "rad" = 0, "fire" = 20, "acid" = 40) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 5, "bio" = 50, "rad" = 0, "fire" = 20, "acid" = 40) resistance_flags = FIRE_PROOF /obj/item/clothing/mask/gas/explorer/attack_self(mob/user) @@ -138,7 +139,7 @@ max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS hoodtype = /obj/item/clothing/head/hooded/explorer/seva - armor = list("melee" = 15, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 25, "bio" = 50, "rad" = 25, "fire" = 100, "acid" = 25) + armor = list("melee" = 15, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 35, "bio" = 50, "rad" = 25, "fire" = 100, "acid" = 25) resistance_flags = FIRE_PROOF | GOLIATH_WEAKNESS /obj/item/clothing/head/hooded/explorer/seva @@ -147,7 +148,7 @@ icon_state = "seva" item_state = "seva" max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT - armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 25, "bio" = 50, "rad" = 25, "fire" = 100, "acid" = 25) + armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 35, "bio" = 50, "rad" = 25, "fire" = 100, "acid" = 25) resistance_flags = FIRE_PROOF | GOLIATH_WEAKNESS /obj/item/clothing/mask/gas/seva diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index 1fd1b31b69..dcd8e1a4ae 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -417,7 +417,7 @@ marker.icon_state = "chronobolt" marker.damage = bonus_value marker.nodamage = FALSE - marker.speed = 2 + marker.pixels_per_second = TILES_TO_PIXELS(5) deadly_shot = FALSE /obj/item/crusher_trophy/blaster_tubes/on_mark_detonation(mob/living/target, mob/living/user) diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index 012d0a12e5..53ce676317 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -39,7 +39,7 @@ if(11) new /obj/item/ship_in_a_bottle(src) if(12) - new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker(src) + new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker/old(src) if(13) new /obj/item/jacobs_ladder(src) if(14) @@ -67,7 +67,7 @@ new /obj/item/grenade/clusterbuster/inferno(src) if(24) new /obj/item/reagent_containers/food/drinks/bottle/holywater/hell(src) - new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor(src) + new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor/old(src) if(25) new /obj/item/book/granter/spell/summonitem(src) if(26) @@ -564,7 +564,7 @@ /obj/item/book_of_babel/attack_self(mob/user) to_chat(user, "You flip through the pages of the book, quickly and conveniently learning every language in existence. Somewhat less conveniently, the aging book crumbles to dust in the process. Whoops.") - user.grant_all_languages(omnitongue=TRUE) + user.grant_all_languages() new /obj/effect/decal/cleanable/ash(get_turf(user)) qdel(src) diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm index bcb196a103..ed6d9e31db 100644 --- a/code/modules/mining/machine_vending.dm +++ b/code/modules/mining/machine_vending.dm @@ -53,6 +53,7 @@ new /datum/data/mining_equipment("Spare Suit Voucher", /obj/item/suit_voucher, 2000), new /datum/data/mining_equipment("Super Resonator", /obj/item/resonator/upgraded, 2500), new /datum/data/mining_equipment("Jump Boots", /obj/item/clothing/shoes/bhop, 2500), + new /datum/data/mining_equipment("Ice hiking boots", /obj/item/clothing/shoes/winterboots/ice_boots, 2500), new /datum/data/mining_equipment("Luxury Shelter Capsule", /obj/item/survivalcapsule/luxury, 3000), new /datum/data/mining_equipment("Luxury Bar Capsule", /obj/item/survivalcapsule/luxuryelite, 10000), new /datum/data/mining_equipment("Nanotrasen Minebot", /mob/living/simple_animal/hostile/mining_drone, 800), @@ -147,9 +148,14 @@ return ..() /obj/machinery/mineral/equipment_vendor/proc/RedeemVoucher(obj/item/mining_voucher/voucher, mob/redeemer) - var/items = list("Survival Capsule and Explorer's Webbing", "Resonator Kit", "Minebot Kit", "Extraction and Rescue Kit", "Crusher Kit", "Mining Conscription Kit") + var/items = list( "Survival Capsule and Explorer's Webbing" = image(icon = 'icons/obj/storage.dmi', icon_state = "explorerpack"), + "Resonator Kit" = image(icon = 'icons/obj/mining.dmi', icon_state = "resonator"), + "Minebot Kit" = image(icon = 'icons/mob/aibots.dmi', icon_state = "mining_drone"), + "Extraction and Rescue Kit" = image(icon = 'icons/obj/fulton.dmi', icon_state = "extraction_pack"), + "Crusher Kit" = image(icon = 'icons/obj/mining.dmi', icon_state = "crusher"), + "Mining Conscription Kit" = image(icon = 'icons/obj/storage.dmi', icon_state = "duffel")) - var/selection = input(redeemer, "Pick your equipment", "Mining Voucher Redemption") as null|anything in items + var/selection = show_radial_menu(redeemer, src, items, require_near = TRUE, tooltips = TRUE) if(!selection || !Adjacent(redeemer) || QDELETED(voucher) || voucher.loc != redeemer) return var/drop_location = drop_location() @@ -320,9 +326,10 @@ new /obj/item/clothing/glasses/meson/prescription(src) /obj/machinery/mineral/equipment_vendor/proc/RedeemSVoucher(obj/item/suit_voucher/voucher, mob/redeemer) - var/items = list("Exo-suit", "SEVA suit") + var/items = list( "Exo-suit" = image(icon = 'icons/obj/clothing/suits.dmi', icon_state = "exo"), + "SEVA suit" = image(icon = 'icons/obj/clothing/suits.dmi', icon_state = "seva")) - var/selection = input(redeemer, "Pick your suit.", "Suit Voucher Redemption") as null|anything in items + var/selection = show_radial_menu(redeemer, src, items, require_near = TRUE, tooltips = TRUE) if(!selection || !Adjacent(redeemer) || QDELETED(voucher) || voucher.loc != redeemer) return var/drop_location = drop_location() diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm index 0c8aef51a8..fb37dcbca0 100644 --- a/code/modules/mining/minebot.dm +++ b/code/modules/mining/minebot.dm @@ -24,7 +24,8 @@ environment_smash = ENVIRONMENT_SMASH_NONE check_friendly_fire = TRUE stop_automated_movement_when_pulled = TRUE - attacktext = "drills" + attack_verb_continuous = "drills" + attack_verb_simple = "drill" attack_sound = 'sound/weapons/circsawhit.ogg' sentience_type = SENTIENCE_MINEBOT speak_emote = list("states") diff --git a/code/modules/mining/money_bag.dm b/code/modules/mining/money_bag.dm index fd5997d3c4..66f99ec40c 100644 --- a/code/modules/mining/money_bag.dm +++ b/code/modules/mining/money_bag.dm @@ -15,7 +15,7 @@ STR.max_w_class = WEIGHT_CLASS_NORMAL STR.max_items = 40 STR.max_combined_w_class = 40 - STR.can_hold = typecacheof(list(/obj/item/coin, /obj/item/stack/spacecash)) + STR.can_hold = typecacheof(list(/obj/item/coin, /obj/item/stack/spacecash, /obj/item/holochip)) /obj/item/storage/bag/money/vault/PopulateContents() new /obj/item/coin/silver(src) diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index 183b4812f2..f6b7110803 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -102,7 +102,22 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ /obj/item/stack/ore/glass/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(..() || !ishuman(hit_atom)) return - var/mob/living/carbon/human/C = hit_atom + var/mob/living/carbon/human/poorsod = hit_atom + eyesand(poorsod) + +/obj/item/stack/ore/glass/attack(mob/living/M, mob/living/user) + if(!ishuman(M)) + return ..() + if(user.zone_selected != BODY_ZONE_PRECISE_EYES && user.zone_selected != BODY_ZONE_HEAD) + return ..() + var/mob/living/carbon/human/poorsod = M + visible_message("[user] throws the sand at [poorsod]'s face!") + if(ishuman(user)) + var/mob/living/carbon/human/sayer = user + sayer.forcesay("POCKET SAAND!!") + eyesand(poorsod) + +/obj/item/stack/ore/glass/proc/eyesand(mob/living/carbon/human/C) if(C.head && C.head.flags_cover & HEADCOVERSEYES) visible_message("[C]'s headgear blocks the sand!") return @@ -116,8 +131,10 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ C.adjustStaminaLoss(15)//the pain from your eyes burning does stamina damage C.confused += 5 to_chat(C, "\The [src] gets into your eyes! The pain, it burns!") + C.forcesay("*scream") qdel(src) + /obj/item/stack/ore/glass/ex_act(severity, target) if (severity == EXPLODE_NONE) return @@ -340,6 +357,9 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ var/datum/material/M = i value += M.value_per_unit * custom_materials[M] +/obj/item/coin/get_item_credit_value() + return value + /obj/item/coin/suicide_act(mob/living/user) user.visible_message("[user] contemplates suicide with \the [src]!") if (!attack_self(user)) @@ -363,12 +383,11 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ /obj/item/coin/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/CC = W if(string_attached) to_chat(user, "There already is a string attached to this coin!") return - if (CC.use(1)) + if (W.use_tool(src, user, 0, 1, max_level = JOB_SKILL_BASIC)) add_overlay("coin_string_overlay") string_attached = 1 to_chat(user, "You attach a string to the coin.") diff --git a/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm b/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm index e38d9b7341..110ac69201 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm @@ -133,6 +133,7 @@ /datum/sprite_accessory/antenna icon = 'modular_citadel/icons/mob/ipc_antennas.dmi' color_src = MUTCOLORS2 + relevant_layers = list(BODY_ADJ_LAYER) recommended_species = list("ipc") /datum/sprite_accessory/antenna/none diff --git a/code/modules/mob/dead/new_player/sprite_accessories/legs_and_taurs.dm b/code/modules/mob/dead/new_player/sprite_accessories/legs_and_taurs.dm index cbb38a3a6a..2ec6da2da8 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/legs_and_taurs.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/legs_and_taurs.dm @@ -64,6 +64,7 @@ taur_mode = STYLE_HOOF_TAURIC alt_taur_mode = STYLE_PAW_TAURIC color_src = MUTCOLORS + extra = TRUE /datum/sprite_accessory/taur/drake name = "Drake" @@ -72,6 +73,12 @@ color_src = MUTCOLORS extra = TRUE +/datum/sprite_accessory/taur/drake/old + name = "Drake (Old)" + icon_state = "drake_old" + color_src = MATRIXED + extra = FALSE + /datum/sprite_accessory/taur/drider name = "Drider" icon_state = "drider" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/tails.dm b/code/modules/mob/dead/new_player/sprite_accessories/tails.dm index 2bb0d6ba77..33dbd7059f 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/tails.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/tails.dm @@ -450,6 +450,18 @@ color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' +/datum/sprite_accessory/tails/human/tamamo_kitsune + name = "Tamamo Kitsune Tails" //Tamamo-no-Tiro, let it be known! + icon_state = "9sune" + color_src = MATRIXED + icon = 'modular_citadel/icons/mob/mam_tails.dmi' + +/datum/sprite_accessory/tails_animated/human/tamamo_kitsune + name = "Tamamo Kitsune Tails" + icon_state = "9sune" + color_src = MATRIXED + icon = 'modular_citadel/icons/mob/mam_tails.dmi' + /datum/sprite_accessory/tails/human/tentacle name = "Tentacle" icon_state = "tentacle" @@ -816,6 +828,14 @@ datum/sprite_accessory/mam_tails/insect name = "Squirrel" icon_state = "squirrel" +/datum/sprite_accessory/mam_tails/tamamo_kitsune + name = "Tamamo Kitsune Tails" + icon_state = "9sune" + +/datum/sprite_accessory/mam_tails_animated/tamamo_kitsune + name = "Tamamo Kitsune Tails" + icon_state = "9sune" + /datum/sprite_accessory/mam_tails/tentacle name = "Tentacle" icon_state = "tentacle" diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index b8e56f3d7c..838de24b60 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -707,7 +707,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp //this is a mob verb instead of atom for performance reasons //see /mob/verb/examinate() in mob.dm for more info //overridden here and in /mob/living for different point span classes and sanity checks -/mob/dead/observer/pointed(atom/A as mob|obj|turf in view()) +/mob/dead/observer/pointed(atom/A as mob|obj|turf in fov_view()) if(!..()) return 0 usr.visible_message("[src] points to [A].") diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index 41f2c7142f..a5275f677d 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -59,7 +59,7 @@ nutrition_ratio *= 1.2 if(satiety > 80) nutrition_ratio *= 1.25 - nutrition = max(0, nutrition - nutrition_ratio * HUNGER_FACTOR) + adjust_nutrition(-nutrition_ratio * HUNGER_FACTOR) blood_volume = min((BLOOD_VOLUME_NORMAL * blood_ratio), blood_volume + 0.5 * nutrition_ratio) //Effects of bloodloss diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm index e8a9b50e98..3547d5f846 100644 --- a/code/modules/mob/living/bloodcrawl.dm +++ b/code/modules/mob/living/bloodcrawl.dm @@ -164,7 +164,7 @@ if(!B) return forceMove(B.loc) - src.client.eye = src + reset_perspective(src) src.visible_message("[src] rises out of the pool of blood!") exit_blood_effect(B) if(iscarbon(src)) diff --git a/code/modules/mob/living/brain/brain.dm b/code/modules/mob/living/brain/brain.dm index 4bca3e7f62..08d415fc3c 100644 --- a/code/modules/mob/living/brain/brain.dm +++ b/code/modules/mob/living/brain/brain.dm @@ -4,6 +4,7 @@ var/emp_damage = 0//Handles a type of MMI damage var/datum/dna/stored/stored_dna // dna var for brain. Used to store dna, brain dna is not considered like actual dna, brain.has_dna() returns FALSE. stat = DEAD //we start dead by default + has_field_of_vision = FALSE //Not really worth it. see_invisible = SEE_INVISIBLE_LIVING possible_a_intents = list(INTENT_HELP, INTENT_HARM) //for mechas speech_span = SPAN_ROBOT diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index 90621ecd3f..687442c1f8 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -51,6 +51,12 @@ var/datum/brain_trauma/BT = X BT.owner = owner BT.on_gain() + if(damage > BRAIN_DAMAGE_MILD) + var/datum/skill_modifier/S + ADD_SKILL_MODIFIER_BODY(/datum/skill_modifier/brain_damage, null, C, S) + if(damage > BRAIN_DAMAGE_SEVERE) + var/datum/skill_modifier/S + ADD_SKILL_MODIFIER_BODY(/datum/skill_modifier/heavy_brain_damage, null, C, S) //Update the body's icon so it doesnt appear debrained anymore C.update_hair() @@ -66,6 +72,8 @@ if((!QDELETED(src) || C) && !no_id_transfer) transfer_identity(C) if(C) + REMOVE_SKILL_MODIFIER_BODY(/datum/skill_modifier/brain_damage, null, C) + REMOVE_SKILL_MODIFIER_BODY(/datum/skill_modifier/heavy_brain_damage, null, C) C.update_hair() /obj/item/organ/brain/prepare_eat() @@ -129,11 +137,11 @@ if(cached_Bdamage <= HEALTH_THRESHOLD_DEAD) //Fixing dead brains yeilds a trauma if((cached_Bdamage <= HEALTH_THRESHOLD_DEAD) && (brainmob.health > HEALTH_THRESHOLD_DEAD)) if(prob(80)) - gain_trauma_type(BRAIN_TRAUMA_MILD) + gain_trauma_type(BRAIN_TRAUMA_MILD, natural_gain = TRUE) else if(prob(50)) - gain_trauma_type(BRAIN_TRAUMA_SEVERE) + gain_trauma_type(BRAIN_TRAUMA_SEVERE, natural_gain = TRUE) else - gain_trauma_type(BRAIN_TRAUMA_SPECIAL) + gain_trauma_type(BRAIN_TRAUMA_SPECIAL, natural_gain = TRUE) return if((organ_flags & ORGAN_FAILING) && O.is_drainable() && O.reagents.has_reagent(/datum/reagent/medicine/mannitol)) //attempt to heal the brain @@ -219,31 +227,6 @@ Insert(C) else ..() -/* TO BE REMOVED, KEPT IN CASE OF BUGS -/obj/item/organ/brain/proc/get_brain_damage() - var/brain_damage_threshold = max_integrity * BRAIN_DAMAGE_INTEGRITY_MULTIPLIER - var/offset_integrity = obj_integrity - (max_integrity - brain_damage_threshold) - . = round((1 - (offset_integrity / brain_damage_threshold)) * BRAIN_DAMAGE_DEATH, DAMAGE_PRECISION) - -/obj/item/organ/brain/proc/adjust_brain_damage(amount, maximum) - var/adjusted_amount - if(amount >= 0 && maximum) - var/brainloss = get_brain_damage() - var/new_brainloss = clamp(brainloss + amount, 0, maximum) - if(brainloss > new_brainloss) //brainloss is over the cap already - return 0 - adjusted_amount = new_brainloss - brainloss - else - adjusted_amount = amount - - adjusted_amount = round(adjusted_amount * BRAIN_DAMAGE_INTEGRITY_MULTIPLIER, DAMAGE_PRECISION) - if(adjusted_amount) - if(adjusted_amount >= DAMAGE_PRECISION) - take_damage(adjusted_amount) - else if(adjusted_amount <= -DAMAGE_PRECISION) - obj_integrity = min(max_integrity, obj_integrity-adjusted_amount) - . = adjusted_amount -*/ /obj/item/organ/brain/applyOrganDamage(var/d, var/maximum = maxHealth) . = ..() @@ -261,18 +244,28 @@ . = ..() //if we're not more injured than before, return without gambling for a trauma if(damage <= prev_damage) + if(damage < prev_damage && owner) + if(prev_damage > BRAIN_DAMAGE_MILD && damage <= BRAIN_DAMAGE_MILD) + REMOVE_SKILL_MODIFIER_BODY(/datum/skill_modifier/brain_damage, null, owner) + if(prev_damage > BRAIN_DAMAGE_SEVERE && damage <= BRAIN_DAMAGE_SEVERE) + REMOVE_SKILL_MODIFIER_BODY(/datum/skill_modifier/heavy_brain_damage, null, owner) return damage_delta = damage - prev_damage if(damage > BRAIN_DAMAGE_MILD) if(prob(damage_delta * (1 + max(0, (damage - BRAIN_DAMAGE_MILD)/100)))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 1% //learn how to do your bloody math properly goddamnit - gain_trauma_type(BRAIN_TRAUMA_MILD) + gain_trauma_type(BRAIN_TRAUMA_MILD, natural_gain = TRUE) + if(prev_damage <= BRAIN_DAMAGE_MILD && owner) + var/datum/skill_modifier/S + ADD_SKILL_MODIFIER_BODY(/datum/skill_modifier/brain_damage, null, owner, S) if(damage > BRAIN_DAMAGE_SEVERE) if(prob(damage_delta * (1 + max(0, (damage - BRAIN_DAMAGE_SEVERE)/100)))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 1% if(prob(20)) - gain_trauma_type(BRAIN_TRAUMA_SPECIAL) + gain_trauma_type(BRAIN_TRAUMA_SPECIAL, natural_gain = TRUE) else - gain_trauma_type(BRAIN_TRAUMA_SEVERE) - + gain_trauma_type(BRAIN_TRAUMA_SEVERE, natural_gain = TRUE) + if(prev_damage <= BRAIN_DAMAGE_SEVERE && owner) + var/datum/skill_modifier/S + ADD_SKILL_MODIFIER_BODY(/datum/skill_modifier/heavy_brain_damage, null, owner, S) if (owner) if(owner.stat < UNCONSCIOUS) //conscious or soft-crit var/brain_message @@ -315,7 +308,7 @@ if(istype(BT, brain_trauma_type) && (BT.resilience <= resilience)) . += BT -/obj/item/organ/brain/proc/can_gain_trauma(datum/brain_trauma/trauma, resilience) +/obj/item/organ/brain/proc/can_gain_trauma(datum/brain_trauma/trauma, resilience, natural_gain = FALSE) if(!ispath(trauma)) trauma = trauma.type if(!initial(trauma.can_gain)) @@ -348,7 +341,7 @@ if(TRAUMA_RESILIENCE_ABSOLUTE) max_traumas = TRAUMA_LIMIT_ABSOLUTE - if(resilience_tier_count >= max_traumas) + if(natural_gain && resilience_tier_count >= max_traumas) return FALSE return TRUE @@ -388,11 +381,11 @@ return actual_trauma //Add a random trauma of a certain subtype -/obj/item/organ/brain/proc/gain_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience) +/obj/item/organ/brain/proc/gain_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience, natural_gain = FALSE) var/list/datum/brain_trauma/possible_traumas = list() for(var/T in subtypesof(brain_trauma_type)) var/datum/brain_trauma/BT = T - if(can_gain_trauma(BT, resilience) && initial(BT.random_gain)) + if(can_gain_trauma(BT, resilience, natural_gain) && initial(BT.random_gain)) possible_traumas += BT if(!LAZYLEN(possible_traumas)) diff --git a/code/modules/mob/living/brain/say.dm b/code/modules/mob/living/brain/say.dm index b7d7e1d7fc..7f6d5215a0 100644 --- a/code/modules/mob/living/brain/say.dm +++ b/code/modules/mob/living/brain/say.dm @@ -25,10 +25,3 @@ /mob/living/brain/treat_message(message) message = capitalize(message) return message - -/mob/living/brain/could_speak_in_language(datum/language/dt) - if(istype(container, /obj/item/mmi/posibrain/soul_vessel)) - // soul vessels can only speak ratvarian. - . = ispath(dt, /datum/language/ratvar) - else - . = ..() diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index bf9854e0b4..442bcf8027 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -140,7 +140,8 @@ Des: Removes all infected images from the alien. /mob/living/carbon/alien/proc/alien_evolve(mob/living/carbon/alien/new_xeno) to_chat(src, "You begin to evolve!") - visible_message("[src] begins to twist and contort!") + visible_message("[src] begins to twist and contort!", + "You begin to twist and contort!") new_xeno.setDir(dir) if(!alien_name_regex.Find(name)) new_xeno.name = name diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index cdb8aff2c6..00ce3a320a 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -27,13 +27,16 @@ In all, this is a lot like the monkey code. /N AdjustUnconscious(-60, FALSE) AdjustSleeping(-100, FALSE) update_mobility() - visible_message("[M.name] nuzzles [src] trying to wake [p_them()] up!") + visible_message("[M.name] nuzzles [src] trying to wake [p_them()] up!", + "[M.name] nuzzles you trying to wake you up!", target = M, + target_message = "You nuzzle [src] trying to wake [p_them()] up!") if(INTENT_DISARM, INTENT_HARM) if(health > 0) M.do_attack_animation(src, ATTACK_EFFECT_BITE) playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) visible_message("[M.name] bites [src]!", \ - "[M.name] bites [src]!", null, COMBAT_MESSAGE_RANGE) + "[M.name] bites [src]!", null, COMBAT_MESSAGE_RANGE, null, M, + "You bite [src]!") adjustBruteLoss(1) log_combat(M, src, "attacked") updatehealth() diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index 42b2c4433b..3827aef8c1 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -21,10 +21,10 @@ Doesn't work on other aliens/AI.*/ . = ..() action = new(src) -/obj/effect/proc_holder/alien/Trigger(mob/living/carbon/user, skip_cost_check) +/obj/effect/proc_holder/alien/Trigger(mob/living/carbon/user, skip_cost_check = FALSE) if(!istype(user)) return TRUE - if(!skip_cost_check || cost_check(check_turf,user)) + if(skip_cost_check || cost_check(check_turf,user)) if(fire(user) && user) // Second check to prevent runtimes when evolving user.adjustPlasma(-plasma_cost) return TRUE diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm index 85204e5ab9..0ce8482ca1 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -66,7 +66,7 @@ if(hit_atom) if(isliving(hit_atom)) var/mob/living/L = hit_atom - if(L.run_block(src, 0, "the [name]", ATTACK_TYPE_TACKLE, 0, src) & BLOCK_SUCCESS) + if(L.mob_run_block(src, 0, "the [name]", ATTACK_TYPE_TACKLE, 0, src, null, null) & BLOCK_SUCCESS) DefaultCombatKnockdown(40, 1, 1) else L.visible_message("[src] pounces on [L]!", "[src] pounces on you!") diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm index c4ccddc559..727a22f844 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm @@ -25,6 +25,7 @@ /mob/living/carbon/alien/humanoid/Initialize() AddAbility(new/obj/effect/proc_holder/alien/regurgitate(null)) . = ..() + AddComponent(/datum/component/footstep, FOOTSTEP_MOB_CLAW, 0.5, -3) /mob/living/carbon/alien/humanoid/restrained(ignore_grab) return handcuffed diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index ce39b329b8..a307433660 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -22,9 +22,6 @@ QDEL_NULL(dna) GLOB.carbon_list -= src -/mob/living/carbon/initialize_footstep() - AddComponent(/datum/component/footstep, 0.6, 2) - /mob/living/carbon/relaymove(mob/user, direction) if(user in src.stomach_contents) if(prob(40)) @@ -199,7 +196,7 @@ to_chat(src, "You set [I] down gently on the ground.") return - adjustStaminaLossBuffered(I.getweight()*2)//CIT CHANGE - throwing items shall be more tiring than swinging em. Doubly so. + adjustStaminaLossBuffered(I.getweight(src, STAM_COST_THROW_MULT, SKILL_THROW_STAM_COST)) if(thrown_thing) visible_message("[src] has thrown [thrown_thing].") @@ -256,7 +253,8 @@ var/obj/item/ITEM = get_item_by_slot(slot) if(ITEM && istype(ITEM, /obj/item/tank) && wear_mask && (wear_mask.clothing_flags & ALLOWINTERNALS)) visible_message("[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name].", \ - "[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name].") + "[usr] tries to [internal ? "close" : "open"] the valve on your [ITEM.name].", \ + target = usr, target_message = "You try to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name].") if(do_mob(usr, src, POCKET_STRIP_DELAY)) if(internal) internal = null @@ -267,7 +265,8 @@ update_internals_hud_icon(1) visible_message("[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name].", \ - "[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name].") + "[usr] [internal ? "opens" : "closes"] the valve on your [ITEM.name].", \ + target = usr, target_message = "You [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name].") /mob/living/carbon/fall(forced) @@ -519,7 +518,7 @@ playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1) var/turf/T = get_turf(src) if(!blood) - nutrition -= lost_nutrition + adjust_nutrition(-lost_nutrition) adjustToxLoss(-3) for(var/i=0 to distance) if(blood) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 0b0edc5742..0ec2f16815 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -9,7 +9,7 @@ if(istype(src.glasses, /obj/item/clothing/glasses)) //glasses var/obj/item/clothing/glasses/GFP = src.glasses number += GFP.flash_protect - + if(istype(src.wear_mask, /obj/item/clothing/mask)) //mask var/obj/item/clothing/mask/MFP = src.wear_mask number += MFP.flash_protect @@ -77,18 +77,10 @@ SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded) /mob/living/carbon/attacked_by(obj/item/I, mob/living/user) - //CIT CHANGES START HERE - combatmode and resting checks - var/totitemdamage = I.force - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - totitemdamage *= 0.5 - if(!CHECK_MOBILITY(user, MOBILITY_STAND)) - totitemdamage *= 0.5 - if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - totitemdamage *= 1.5 - //CIT CHANGES END HERE + var/totitemdamage = pre_attacked_by(I, user) var/impacting_zone = (user == src)? check_zone(user.zone_selected) : ran_zone(user.zone_selected) var/list/block_return = list() - if((user != src) && (run_block(I, totitemdamage, "the [I]", ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone, return_list = block_return) & BLOCK_SUCCESS)) + if((user != src) && (mob_run_block(I, totitemdamage, "the [I]", ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone, block_return) & BLOCK_SUCCESS)) return FALSE totitemdamage = block_calculate_resultant_damage(totitemdamage, block_return) var/obj/item/bodypart/affecting = get_bodypart(impacting_zone) @@ -96,7 +88,7 @@ affecting = bodyparts[1] SEND_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting) send_item_attack_message(I, user, affecting.name) - I.do_stagger_action(src, user) + I.do_stagger_action(src, user, totitemdamage) if(I.force) apply_damage(totitemdamage, I.damtype, affecting) //CIT CHANGE - replaces I.force with totitemdamage if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC) @@ -189,7 +181,8 @@ M.powerlevel = 0 visible_message("The [M.name] has shocked [src]!", \ - "The [M.name] has shocked [src]!") + "The [M.name] has shocked you!", target = M, + target_message = "You have shocked [src]!") do_sparks(5, TRUE, src) var/power = M.powerlevel + rand(0,3) @@ -238,38 +231,44 @@ var/obj/item/organ/O = X O.emp_act(severity) +///Adds to the parent by also adding functionality to propagate shocks through pulling and doing some fluff effects. /mob/living/carbon/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE) - if((flags & SHOCK_TESLA) && (flags_1 & TESLA_IGNORE_1)) - return FALSE - if(HAS_TRAIT(src, TRAIT_SHOCKIMMUNE)) - return FALSE - shock_damage *= siemens_coeff - if(dna && dna.species) - shock_damage *= dna.species.siemens_coeff - if(shock_damage < 1) - return 0 - if(reagents.has_reagent(/datum/reagent/teslium)) - shock_damage *= 1.5 //If the mob has teslium in their body, shocks are 50% more damaging! - if((flags & SHOCK_ILLUSION)) - adjustStaminaLoss(shock_damage) - else - take_overall_damage(0,shock_damage) - visible_message( - "[src] was shocked by \the [source]!", \ - "You feel a powerful shock coursing through your body!", \ - "You hear a heavy electrical crack." \ - ) - jitteriness += 1000 //High numbers for violent convulsions + . = ..() + if(!.) + return + //Propagation through pulling, fireman carry + if(!(flags & SHOCK_ILLUSION)) + var/list/shocking_queue = list() + if(iscarbon(pulling) && source != pulling) + shocking_queue += pulling + if(iscarbon(pulledby) && source != pulledby) + shocking_queue += pulledby + if(iscarbon(buckled) && source != buckled) + shocking_queue += buckled + for(var/mob/living/carbon/carried in buckled_mobs) + if(source != carried) + shocking_queue += carried + //Found our victims, now lets shock them all + for(var/victim in shocking_queue) + var/mob/living/carbon/C = victim + C.electrocute_act(shock_damage*0.75, src, 1, flags) + //Stun + var/should_stun = (!(flags & SHOCK_TESLA) || siemens_coeff > 0.5) && !(flags & SHOCK_NOSTUN) + if(should_stun) + Stun(40) + //Jitter and other fluff. + jitteriness += 1000 do_jitter_animation(jitteriness) stuttering += 2 - if((!(flags & SHOCK_TESLA) || siemens_coeff > 0.5) && !(flags & SHOCK_NOSTUN)) - Stun(40) - spawn(20) - jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less - if((!(flags & SHOCK_TESLA) || siemens_coeff > 0.5) && !(flags & SHOCK_NOSTUN)) - DefaultCombatKnockdown(60) + addtimer(CALLBACK(src, .proc/secondary_shock, should_stun), 20) return shock_damage +///Called slightly after electrocute act to reduce jittering and apply a secondary stun. +/mob/living/carbon/proc/secondary_shock(should_stun) + jitteriness = max(jitteriness - 990, 10) + if(should_stun) + DefaultCombatKnockdown(60) + /mob/living/carbon/proc/help_shake_act(mob/living/carbon/M) if(on_fire) to_chat(M, "You can't put [p_them()] out with just your bare hands!") @@ -277,19 +276,21 @@ if(health >= 0 && !(HAS_TRAIT(src, TRAIT_FAKEDEATH))) var/friendly_check = FALSE - if(run_block(M, 0, M.name, ATTACK_TYPE_UNARMED)) + if(mob_run_block(M, 0, M.name, ATTACK_TYPE_UNARMED, 0, null, null, null)) return if(lying) if(buckled) to_chat(M, "You need to unbuckle [src] first to do that!") return M.visible_message("[M] shakes [src] trying to get [p_them()] up!", \ - "You shake [src] trying to get [p_them()] up!") + "You shake [src] trying to get [p_them()] up!", target = src, + target_message = "[M] shakes you trying to get you up!") else if(M.zone_selected == BODY_ZONE_PRECISE_MOUTH) // I ADDED BOOP-EH-DEH-NOSEH - Jon M.visible_message( \ "[M] boops [src]'s nose.", \ - "You boop [src] on the nose.", ) + "You boop [src] on the nose.", target = src, + target_message = "[M] boops your nose.") playsound(src, 'sound/items/Nose_boop.ogg', 50, 0) else if(check_zone(M.zone_selected) == BODY_ZONE_HEAD) @@ -298,7 +299,8 @@ S = dna.species M.visible_message("[M] gives [src] a pat on the head to make [p_them()] feel better!", \ - "You give [src] a pat on the head to make [p_them()] feel better!") + "You give [src] a pat on the head to make [p_them()] feel better!", target = src, + target_message = "[M] gives you a pat on the head to make you feel better!") SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "headpat", /datum/mood_event/headpat) friendly_check = TRUE if(S?.can_wag_tail(src) && !dna.species.is_wagging_tail()) @@ -311,11 +313,13 @@ else if(check_zone(M.zone_selected) == BODY_ZONE_R_ARM || check_zone(M.zone_selected) == BODY_ZONE_L_ARM) M.visible_message( \ "[M] shakes [src]'s hand.", \ - "You shake [src]'s hand.", ) + "You shake [src]'s hand.", target = src, + target_message = "[M] shakes your hand.") else M.visible_message("[M] hugs [src] to make [p_them()] feel better!", \ - "You hug [src] to make [p_them()] feel better!") + "You hug [src] to make [p_them()] feel better!", target = src,\ + target_message = "[M] hugs you to make you feel better!") SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "hug", /datum/mood_event/hug) friendly_check = TRUE @@ -437,3 +441,17 @@ var/obj/item/organ/ears/ears = getorganslot(ORGAN_SLOT_EARS) if(istype(ears) && !ears.deaf) . = TRUE + +/mob/living/carbon/getBruteLoss_nonProsthetic() + var/amount = 0 + for(var/obj/item/bodypart/BP in bodyparts) + if (BP.status < 2) + amount += BP.brute_dam + return amount + +/mob/living/carbon/getFireLoss_nonProsthetic() + var/amount = 0 + for(var/obj/item/bodypart/BP in bodyparts) + if (BP.status < 2) + amount += BP.burn_dam + return amount diff --git a/code/modules/mob/living/carbon/carbon_movement.dm b/code/modules/mob/living/carbon/carbon_movement.dm index fa060d8b34..cc390b9329 100644 --- a/code/modules/mob/living/carbon/carbon_movement.dm +++ b/code/modules/mob/living/carbon/carbon_movement.dm @@ -24,11 +24,12 @@ . = ..() if(. && (movement_type & FLOATING)) //floating is easy if(HAS_TRAIT(src, TRAIT_NOHUNGER)) - nutrition = NUTRITION_LEVEL_FED - 1 //just less than feeling vigorous + set_nutrition(NUTRITION_LEVEL_FED - 1) //just less than feeling vigorous else if(nutrition && stat != DEAD) - nutrition -= HUNGER_FACTOR/10 + var/loss = HUNGER_FACTOR/10 if(m_intent == MOVE_INTENT_RUN) - nutrition -= HUNGER_FACTOR/10 + loss *= 2 + adjust_nutrition(loss) /mob/living/carbon/can_move_under_living(mob/living/other) . = ..() diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index adca193ce0..5528669afa 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -63,7 +63,7 @@ /mob/living/carbon/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE) - if (!forced && amount < 0 && HAS_TRAIT(src,TRAIT_NONATURALHEAL)) + if(!forced && amount < 0 && HAS_TRAIT(src,TRAIT_NONATURALHEAL)) return FALSE if(!forced && (status_flags & GODMODE)) return FALSE @@ -74,7 +74,7 @@ return amount /mob/living/carbon/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE) - if (!forced && amount < 0 && HAS_TRAIT(src,TRAIT_NONATURALHEAL)) //Vamps don't heal naturally. + if(!forced && amount < 0 && HAS_TRAIT(src,TRAIT_NONATURALHEAL)) //Vamps don't heal naturally. return FALSE if(!forced && (status_flags & GODMODE)) return FALSE diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index 60fa395319..4cf82bb0b4 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -25,7 +25,8 @@ if(M in stomach_contents) stomach_contents.Remove(M) M.forceMove(Tsec) - visible_message("[M] bursts out of [src]!") + M.visible_message("[M] bursts out of [src]!", + "You burst out of [src]!") ..() /mob/living/carbon/spill_organs(no_brain, no_organs, no_bodyparts) diff --git a/code/modules/mob/living/carbon/give.dm b/code/modules/mob/living/carbon/give.dm deleted file mode 100644 index a712240622..0000000000 --- a/code/modules/mob/living/carbon/give.dm +++ /dev/null @@ -1,58 +0,0 @@ -/mob/living/verb/give() - set category = "IC" - set name = "Give" - set src in oview(1) //Cannot handle giving shit to mobs on your own tile, but it's a small, small loss - - give_item(usr) - -/mob/living/proc/give_item(mob/living/carbon/user) - - -/mob/living/carbon/give_item(mob/living/carbon/user) - if(!istype(user)) - return - if(src.stat == 2 || user.stat == 2 || src.client == null) - return - if(src.handcuffed) - user << "Those hands are cuffed right now." - return //Can't receive items while cuffed - var/obj/item/I - if(user.get_active_held_item() == null) - user << "You don't have anything in your [get_held_index_name(get_held_index_of_item(I))] to give to [src]." - return - I = user.get_active_held_item() - if(!I) - return - if(src == user) //Shouldn't happen - user << "You tried to give yourself \the [I], but you didn't want it." - return - if(get_empty_held_index_for_side()) - switch(alert(src, "[user] wants to give you \a [I]?", , "Yes", "No")) - if("Yes") - if(!I) - return - if(!Adjacent(user)) - user <<"You need to stay still while giving an object." - src << "[user] moved away."//What an asshole - - return - if(user.get_active_held_item() != I) - user << "You need to keep the item in your hand." - src << "[user] has put \the [I] away!" - return - if(!get_empty_held_index_for_side()) - user << "Your hands are full." - user << "Their hands are full." - return - if(!user.dropItemToGround(I)) - src << "[user] can't let go of \the [I]!" - user << "You can't seem to let go of \the [I]." - return - - src.put_in_hands(I) - update_inv_hands() - src.visible_message("[user] handed \the [I] to [src].") - if("No") - src.visible_message("[user] tried to hand \the [I] to [src] but \he didn't want it.") - else - user << "[src]'s hands are full." diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm index 7918e303e8..24eb5d7234 100644 --- a/code/modules/mob/living/carbon/human/dummy.dm +++ b/code/modules/mob/living/carbon/human/dummy.dm @@ -43,5 +43,6 @@ GLOBAL_LIST_EMPTY(dummy_mob_list) return var/mob/living/carbon/human/dummy/D = GLOB.human_dummy_list[slotnumber] if(istype(D)) + D.set_species(/datum/species/human,icon_update = TRUE, pref_load = TRUE) //for some fucking reason, if you don't change the species every time, some species will dafault certain things when it's their own species on the mannequin two times in a row, like lizards losing spines and tails setting to smooth. If you can find a fix for this that isn't this, good on you D.wipe_state() D.in_use = FALSE diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 5d097c0f54..007bca3518 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -26,6 +26,7 @@ physiology = new() AddComponent(/datum/component/personal_crafting) + AddComponent(/datum/component/footstep, FOOTSTEP_MOB_HUMAN, 1, 2) . = ..() if(CONFIG_GET(flag/disable_stambuffer)) @@ -38,8 +39,9 @@ . = ..() if(!CONFIG_GET(flag/disable_human_mood)) AddComponent(/datum/component/mood) - AddElement(/datum/element/flavor_text/carbon) + AddElement(/datum/element/flavor_text/carbon, _name = "Flavor Text", _save_key = "flavor_text") AddElement(/datum/element/flavor_text, "", "Temporary Flavor Text", "This should be used only for things pertaining to the current round!") + AddElement(/datum/element/flavor_text, _name = "OOC Notes", _addendum = "Put information on ERP/vore/lewd-related preferences here. THIS SHOULD NOT CONTAIN REGULAR FLAVORTEXT!!", _always_show = TRUE, _save_key = "ooc_notes", _examine_no_preview = TRUE) /mob/living/carbon/human/Destroy() QDEL_NULL(physiology) @@ -1059,6 +1061,9 @@ if(health_deficiency >= 40) add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown, TRUE, (health_deficiency-39) / 75) add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying, TRUE, (health_deficiency-39) / 25) + else + remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown) + remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying) else remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown) remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 856c57687f..3a2d0535e6 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -102,11 +102,15 @@ . = ..(user, TRUE) if(.) return - var/hulk_verb = pick("smash","pummel") + var/hulk_verb_continous = "smashes" + var/hulk_verb_simple = "smash" + if(prob(50)) + hulk_verb_continous = "pummels" + hulk_verb_simple = "pummel" playsound(loc, user.dna.species.attack_sound, 25, 1, -1) - var/message = "[user] has [hulk_verb]ed [src]!" - visible_message("[message]", \ - "[message]") + visible_message("[user] [hulk_verb_continous] [src]!", \ + "[user] [hulk_verb_continous] you!", null, COMBAT_MESSAGE_RANGE, null, user, + "You [hulk_verb_simple] [src]!") adjustBruteLoss(15) return 1 @@ -130,14 +134,16 @@ var/obj/item/I = get_active_held_item() if(I && dropItemToGround(I)) playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) - visible_message("[M] disarmed [src]!", \ - "[M] disarmed [src]!") + visible_message("[M] has disarmed [src]!", \ + "[M] has disarmed you!", null, COMBAT_MESSAGE_RANGE, null, M, + "You have disarmed [src]!") else if(!M.client || prob(5)) // only natural monkeys get to stun reliably, (they only do it occasionaly) playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) DefaultCombatKnockdown(100) log_combat(M, src, "tackled") visible_message("[M] has tackled down [src]!", \ - "[M] has tackled down [src]!") + "[M] has tackled you down!", null, COMBAT_MESSAGE_RANGE, null, M, + "You have tackled [src] down!") if(M.limb_destroyer) dismembering_strike(M, affecting.body_zone) @@ -159,7 +165,8 @@ if(!damage) playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1) visible_message("[M] has lunged at [src]!", \ - "[M] has lunged at [src]!") + "[M] has lunged at you!", target = M, \ + target_message = "You have lunged at [src]!") return 0 var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) if(!affecting) @@ -168,7 +175,8 @@ playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) visible_message("[M] has slashed at [src]!", \ - "[M] has slashed at [src]!") + "[M] has slashed at you!", target = M, \ + target_message = "You have slashed at [src]!") log_combat(M, src, "attacked") if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful return 1 @@ -178,14 +186,16 @@ var/obj/item/I = get_active_held_item() if(I && dropItemToGround(I)) playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) - visible_message("[M] disarmed [src]!", \ - "[M] disarmed [src]!") + visible_message("[M] has disarmed [src]!", \ + "[M] has disarmed you!", target = M, \ + target_message = "You have disarmed [src]!") else playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) DefaultCombatKnockdown(M.meleeKnockdownPower) log_combat(M, src, "tackled") visible_message("[M] has tackled down [src]!", \ - "[M] has tackled down [src]!") + "[M] has tackled you down!", target = M, \ + target_message = "You have tackled down [src]!") /mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L) . = ..() @@ -268,7 +278,8 @@ updatehealth() visible_message("[M.name] has hit [src]!", \ - "[M.name] has hit [src]!", null, COMBAT_MESSAGE_RANGE) + "[M.name] has hit you!", null, COMBAT_MESSAGE_RANGE, target = M, + target_message = "You have hit [src]!") log_combat(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])") else @@ -348,40 +359,34 @@ apply_damage(5, BRUTE, affecting, run_armor_check(affecting, "melee")) -//Added a safety check in case you want to shock a human mob directly through electrocute_act. +///Calculates the siemens coeff based on clothing and species, can also restart hearts. /mob/living/carbon/human/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE) - if(flags & SHOCK_TESLA) - var/total_coeff = 1 - if(gloves) - var/obj/item/clothing/gloves/G = gloves - if(G.siemens_coefficient <= 0) - total_coeff -= 0.5 + //Calculates the siemens coeff based on clothing. Completely ignores the arguments + if(flags & SHOCK_TESLA) //I hate this entire block. This gets the siemens_coeff for tesla shocks + if(gloves && gloves.siemens_coefficient <= 0) + siemens_coeff -= 0.5 if(wear_suit) - var/obj/item/clothing/suit/S = wear_suit - if(S.siemens_coefficient <= 0) - total_coeff -= 0.95 - else if(S.siemens_coefficient == (-1)) - total_coeff -= 1 - siemens_coeff = total_coeff - if(flags_1 & TESLA_IGNORE_1) - siemens_coeff = 0 - else if(!(flags & SHOCK_NOGLOVES)) - var/gloves_siemens_coeff = 1 + if(wear_suit.siemens_coefficient == -1) + siemens_coeff -= 1 + else if(wear_suit.siemens_coefficient <= 0) + siemens_coeff -= 0.95 + siemens_coeff = max(siemens_coeff, 0) + else if(!(flags & SHOCK_NOGLOVES)) //This gets the siemens_coeff for all non tesla shocks if(gloves) - var/obj/item/clothing/gloves/G = gloves - gloves_siemens_coeff = G.siemens_coefficient - siemens_coeff = gloves_siemens_coeff - if(undergoing_cardiac_arrest() && !(flags & SHOCK_ILLUSION)) - if(shock_damage * siemens_coeff >= 1 && prob(25)) - var/obj/item/organ/heart/heart = getorganslot(ORGAN_SLOT_HEART) - heart.beating = TRUE - if(stat == CONSCIOUS) - to_chat(src, "You feel your heart beating again!") + siemens_coeff *= gloves.siemens_coefficient siemens_coeff *= physiology.siemens_coeff . = ..() - if(.) - electrocution_animation(40) - + //Don't go further if the shock was blocked/too weak. + if(!.) + return + //Note we both check that the user is in cardiac arrest and can actually heartattack + //If they can't, they're missing their heart and this would runtime + if(undergoing_cardiac_arrest() && can_heartattack() && !(flags & SHOCK_ILLUSION)) + if(shock_damage * siemens_coeff >= 1 && prob(25)) + var/obj/item/organ/heart/heart = getorganslot(ORGAN_SLOT_HEART) + if(heart.Restart() && stat == CONSCIOUS) + to_chat(src, "You feel your heart beating again!") + electrocution_animation(40) /mob/living/carbon/human/emp_act(severity) . = ..() diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 80474aa5ef..af17dccaae 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -9,6 +9,7 @@ /// Enable stamina combat combat_flags = COMBAT_FLAGS_DEFAULT status_flags = CANSTUN|CANKNOCKDOWN|CANUNCONSCIOUS|CANPUSH|CANSTAGGER + has_field_of_vision = FALSE //Handled by species. blocks_emissive = EMISSIVE_BLOCK_UNIQUE @@ -70,4 +71,5 @@ var/creamed = FALSE //to use with creampie overlays var/static/list/can_ride_typecache = typecacheof(list(/mob/living/carbon/human, /mob/living/simple_animal/slime, /mob/living/simple_animal/parrot)) var/lastpuke = 0 + var/account_id var/last_fire_update diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 7b3953e40e..7c256f5367 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -127,6 +127,17 @@ to_chat(src, "Your fingers don't fit in the trigger guard!") return FALSE +/mob/living/carbon/human/proc/get_bank_account() + RETURN_TYPE(/datum/bank_account) + var/datum/bank_account/account + var/obj/item/card/id/I = get_idcard() + + if(I && I.registered_account) + account = I.registered_account + return account + + return FALSE + /mob/living/carbon/human/can_see_reagents() . = ..() if(.) //No need to run through all of this if it's already true. diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 580b0aaaf0..8de143e2bd 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -277,3 +277,65 @@ qdel(slot) for(var/obj/item/I in held_items) qdel(I) + +/mob/living/carbon/human/proc/smart_equipbag() // take most recent item out of bag or place held item in bag + if(incapacitated()) + return + var/obj/item/thing = get_active_held_item() + var/obj/item/equipped_back = get_item_by_slot(SLOT_BACK) + if(!equipped_back) // We also let you equip a backpack like this + if(!thing) + to_chat(src, "You have no backpack to take something out of!") + return + if(equip_to_slot_if_possible(thing, ITEM_SLOT_BACK)) + update_inv_hands() + return + if(!SEND_SIGNAL(equipped_back, COMSIG_CONTAINS_STORAGE)) // not a storage item + if(!thing) + equipped_back.attack_hand(src) + else + to_chat(src, "You can't fit anything in!") + return + if(thing) // put thing in backpack + if(!SEND_SIGNAL(equipped_back, COMSIG_TRY_STORAGE_INSERT, thing, src)) + to_chat(src, "You can't fit anything in!") + return + if(!equipped_back.contents.len) // nothing to take out + to_chat(src, "There's nothing in your backpack to take out!") + return + var/obj/item/stored = equipped_back.contents[equipped_back.contents.len] + if(!stored || stored.on_found(src)) + return + stored.attack_hand(src) // take out thing from backpack + return + +/mob/living/carbon/human/proc/smart_equipbelt() // put held thing in belt or take most recent item out of belt + if(incapacitated()) + return + var/obj/item/thing = get_active_held_item() + var/obj/item/equipped_belt = get_item_by_slot(SLOT_BELT) + if(!equipped_belt) // We also let you equip a belt like this + if(!thing) + to_chat(src, "You have no belt to take something out of!") + return + if(equip_to_slot_if_possible(thing, ITEM_SLOT_BELT)) + update_inv_hands() + return + if(!SEND_SIGNAL(equipped_belt, COMSIG_CONTAINS_STORAGE)) // not a storage item + if(!thing) + equipped_belt.attack_hand(src) + else + to_chat(src, "You can't fit anything in!") + return + if(thing) // put thing in belt + if(!SEND_SIGNAL(equipped_belt, COMSIG_TRY_STORAGE_INSERT, thing, src)) + to_chat(src, "You can't fit anything in!") + return + if(!equipped_belt.contents.len) // nothing to take out + to_chat(src, "There's nothing in your belt to take out!") + return + var/obj/item/stored = equipped_belt.contents[equipped_belt.contents.len] + if(!stored || stored.on_found(src)) + return + stored.attack_hand(src) // take out thing from belt + return diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/login.dm new file mode 100644 index 0000000000..a89921143a --- /dev/null +++ b/code/modules/mob/living/carbon/human/login.dm @@ -0,0 +1,4 @@ +/mob/living/carbon/human/Login() + ..() + if(dna?.species?.has_field_of_vision && CONFIG_GET(flag/use_field_of_vision)) + LoadComponent(/datum/component/field_of_vision, field_of_vision_type) diff --git a/code/modules/mob/living/carbon/human/physiology.dm b/code/modules/mob/living/carbon/human/physiology.dm index 4d411deb53..fd0df0bde9 100644 --- a/code/modules/mob/living/carbon/human/physiology.dm +++ b/code/modules/mob/living/carbon/human/physiology.dm @@ -25,5 +25,8 @@ var/do_after_speed = 1 //Speed mod for do_after. Lower is better. If temporarily adjusting, please only modify using *= and /=, so you don't interrupt other calculations. + /// footstep type override for both shoeless and not footstep sounds. + var/footstep_type + /datum/physiology/New() armor = new diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 7205a4bf59..6f022bdfec 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -10,6 +10,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows + var/has_field_of_vision = TRUE //Species Icon Drawing Offsets - Pixel X, Pixel Y, Aka X = Horizontal and Y = Vertical, from bottom left corner var/list/offset_features = list( @@ -49,6 +50,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/blacklisted = 0 //Flag to exclude from green slime core species. var/dangerous_existence //A flag for transformation spells that tells them "hey if you turn a person into one of these without preperation, they'll probably die!" var/say_mod = "says" // affects the speech message + var/species_language_holder = /datum/language_holder var/list/mutant_bodyparts = list() // Visible CURRENT bodyparts that are unique to a species. Changes to this list for non-species specific bodyparts (ie cat ears and tails) should be assigned at organ level if possible. Layer hiding is handled by handle_mutant_bodyparts() below. var/list/mutant_organs = list() //Internal organs that are unique to this race. var/speedmod = 0 // this affects the race's speed. positive numbers make it move slower, negative numbers make it move faster @@ -103,6 +105,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/whitelist = list() //List the ckeys that can use this species, if it's whitelisted.: list("John Doe", "poopface666", "SeeALiggerPullTheTrigger") Spaces & capitalization can be included or ignored entirely for each key as it checks for both. var/icon_limbs //Overrides the icon used for the limbs of this species. Mainly for downstream, and also because hardcoded icons disgust me. Implemented and maintained as a favor in return for a downstream's implementation of synths. + /// Our default override for typing indicator state + var/typing_indicator_state + /////////// // PROCS // /////////// @@ -327,6 +332,24 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(mutant_bodyparts["meat_type"]) //I can't believe it's come to the meat H.type_of_meat = GLOB.meat_types[H.dna.features["meat_type"]] + if(H.physiology) + if(mutant_bodyparts["taur"]) + var/datum/sprite_accessory/taur/T = GLOB.taur_list[H.dna.features["taur"]] + switch(T?.taur_mode) + if(STYLE_HOOF_TAURIC) + H.physiology.footstep_type = FOOTSTEP_MOB_SHOE + if(STYLE_PAW_TAURIC) + H.physiology.footstep_type = FOOTSTEP_MOB_CLAW + if(STYLE_SNEK_TAURIC) + H.physiology.footstep_type = FOOTSTEP_MOB_CRAWL + else + H.physiology.footstep_type = null + else + H.physiology.footstep_type = null + + if(H.client && has_field_of_vision && CONFIG_GET(flag/use_field_of_vision)) + H.LoadComponent(/datum/component/field_of_vision, H.field_of_vision_type) + C.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/species, TRUE, multiplicative_slowdown = speedmod) SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species) @@ -360,6 +383,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) C.dna.mutation_index[location] = new_species.inert_mutation C.dna.mutation_index[new_species.inert_mutation] = create_sequence(new_species.inert_mutation) + if(!new_species.has_field_of_vision && has_field_of_vision && ishuman(C) && CONFIG_GET(flag/use_field_of_vision)) + var/datum/component/field_of_vision/F = C.GetComponent(/datum/component/field_of_vision) + if(F) + qdel(F) + SEND_SIGNAL(C, COMSIG_SPECIES_LOSS, src) /datum/species/proc/handle_hair(mob/living/carbon/human/H, forced_colour) @@ -1287,7 +1315,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.Jitter(5) hunger_rate = 3 * HUNGER_FACTOR hunger_rate *= H.physiology.hunger_mod - H.nutrition = max(0, H.nutrition - hunger_rate) + H.adjust_nutrition(-hunger_rate) if (H.nutrition > NUTRITION_LEVEL_FULL) @@ -1394,7 +1422,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) /datum/species/proc/grab(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) if(target.check_martial_melee_block()) - target.visible_message("[target] blocks [user]'s grab attempt!") + target.visible_message("[target] blocks [user]'s grab attempt!", target = user, \ + target_message = "[target] blocks your grab attempt!") return 0 if(attacker_style && attacker_style.grab_act(user,target)) return 1 @@ -1410,7 +1439,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) to_chat(user, "You're too exhausted.") //CITADEL CHANGE - ditto return FALSE //CITADEL CHANGE - ditto if(target.check_martial_melee_block()) - target.visible_message("[target] blocks [user]'s attack!") + target.visible_message("[target] blocks [user]'s attack!", target = user, \ + target_message = "[target] blocks your attack!") return FALSE if(HAS_TRAIT(user, TRAIT_PUGILIST))//CITADEL CHANGE - makes punching cause staminaloss but funny martial artist types get a discount @@ -1465,8 +1495,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(!damage || !affecting || prob(miss_chance))//future-proofing for species that have 0 damage/weird cases where no zone is targeted playsound(target.loc, user.dna.species.miss_sound, 25, TRUE, -1) target.visible_message("[user]'s [atk_verb] misses [target]!", \ - "You avoid [user]'s [atk_verb]!", "You hear a swoosh!", COMBAT_MESSAGE_RANGE, user) - to_chat(user, "Your [atk_verb] misses [target]!") + "You avoid [user]'s [atk_verb]!", "You hear a swoosh!", null, COMBAT_MESSAGE_RANGE, null, \ + user, "Your [atk_verb] misses [target]!") log_combat(user, target, "attempted to punch") return FALSE @@ -1475,8 +1505,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) playsound(target.loc, user.dna.species.attack_sound, 25, 1, -1) - target.visible_message("[user] has [atk_verb]ed [target]!", \ - "[user] has [atk_verb]ed [target]!", null, COMBAT_MESSAGE_RANGE) + target.visible_message("[user] [atk_verb]s [target]!", \ + "[user] [atk_verb]s you!", null, COMBAT_MESSAGE_RANGE, null, \ + user, "You [atk_verb] [target]!") target.lastattacker = user.real_name target.lastattackerckey = user.ckey @@ -1498,8 +1529,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if((punchedstam > 50) && prob(punchedstam*0.5)) //If our punch victim has been hit above the threshold, and they have more than 50 stamina damage, roll for stun, probability of 1% per 2 stamina damage target.visible_message("[user] knocks [target] down!", \ - "You're knocked down by [user]!", "You hear aggressive shuffling followed by a loud thud!", COMBAT_MESSAGE_RANGE, user) - to_chat(user, "You knock [target] down!") + "You're knocked down by [user]!", + "You hear aggressive shuffling followed by a loud thud!", COMBAT_MESSAGE_RANGE, null, + user, "You knock [target] down!") var/knockdown_duration = 40 + (punchedstam + (punchedbrute*0.5))*0.8 - armor_block target.DefaultCombatKnockdown(knockdown_duration) @@ -1531,23 +1563,20 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/target_aiming_for_groin = target.zone_selected == "groin" if(target.check_martial_melee_block()) //END EDIT - target.visible_message("[target] blocks [user]'s disarm attempt!") + target.visible_message("[target] blocks [user]'s disarm attempt!", target = user, \ + target_message = "[target] blocks your disarm attempt!") return FALSE if(IS_STAMCRIT(user)) to_chat(user, "You're too exhausted!") return FALSE - else if(target.check_block()) - target.visible_message("[target] blocks [user]'s disarm attempt!") - return FALSE else if(aim_for_mouth && ( target_on_help || target_restrained || target_aiming_for_mouth)) playsound(target.loc, 'sound/weapons/slap.ogg', 50, 1, -1) - user.visible_message(\ - "\The [user] slaps \the [target] in the face!",\ - "You slap [user == target ? "yourself" : "\the [target]"] in the face! ",\ - "You hear a slap." - ) + target.visible_message(\ + "\The [user] slaps [user == target ? "[user.p_them()]self" : "\the [target]"] in the face!",\ + "[user] slaps you in the face! ",\ + "You hear a slap.", target = user, target_message = "You slap [user == target ? "yourself" : "\the [target]"] in the face! ") user.do_attack_animation(target, ATTACK_EFFECT_FACE_SLAP) user.adjustStaminaLossBuffered(3) if (!HAS_TRAIT(target, TRAIT_PERMABONER)) @@ -1565,11 +1594,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if (!HAS_TRAIT(target, TRAIT_PERMABONER)) stop_wagging_tail(target) playsound(target.loc, 'sound/weapons/slap.ogg', 50, 1, -1) - user.visible_message(\ - "\The [user] slaps \the [target]'s ass!",\ - "You slap [user == target ? "your" : "\the [target]'s"] ass!",\ - "You hear a slap." - ) + target.visible_message(\ + "\The [user] slaps [user == target ? "[user.p_their()] own" : "\the [target]'s"] ass!",\ + "[user] slaps your ass! ",\ + "You hear a slap.", target = user, target_message = "You slap [user == target ? "your own" : "\the [target]'s"] ass! ") + return FALSE else @@ -1588,21 +1617,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) //var/randomized_zone = ran_zone(user.zone_selected) CIT CHANGE - comments out to prevent compiling errors SEND_SIGNAL(target, COMSIG_HUMAN_DISARM_HIT, user, user.zone_selected) if(target.pulling == user) - target.visible_message("[user] wrestles out of [target]'s grip!") + target.visible_message("[user] wrestles out of [target]'s grip!", \ + "[user] wrestles out of your grip!", target = user, \ + target_message = "You wrestle out of [target]'s grip!") target.stop_pulling() playsound(target, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) log_combat(user, target, "disarmed out of grab from") return - //var/obj/item/bodypart/affecting = target.get_bodypart(randomized_zone) CIT CHANGE - comments this out to prevent compile errors due to the below commented out bit var/randn = rand(1, 100) - /*if(randn <= 25) CITADEL CHANGE - moves disarm push attempts to right click - playsound(target, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - target.visible_message("[user] has pushed [target]!", - "[user] has pushed [target]!", null, COMBAT_MESSAGE_RANGE) - target.apply_effect(40, EFFECT_KNOCKDOWN, target.run_armor_check(affecting, "melee", "Your armor prevents your fall!", "Your armor softens your fall!")) - target.forcesay(GLOB.hit_appends) - log_combat(user, target, "pushed over") - return*/ if(!(target.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) // CITADEL CHANGE randn += -10 //CITADEL CHANGE - being out of combat mode makes it easier for you to get disarmed if(!CHECK_MOBILITY(user, MOBILITY_STAND)) //CITADEL CHANGE @@ -1619,13 +1641,16 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(randn <= 35)//CIT CHANGE - changes this back to a 35% chance to accomodate for the above being commented out in favor of right-click pushing var/obj/item/I = null if(target.pulling) - target.visible_message("[user] has broken [target]'s grip on [target.pulling]!") + target.visible_message("[user] has broken [target]'s grip on [target.pulling]!", \ + "[user] has broken your grip on [target.pulling]!", target = user, \ + target_message = "You have broken [target]'s grip on [target.pulling]!") target.stop_pulling() else I = target.get_active_held_item() if(target.dropItemToGround(I)) target.visible_message("[user] has disarmed [target]!", \ - "[user] has disarmed [target]!", null, COMBAT_MESSAGE_RANGE) + "[user] has disarmed you!", null, COMBAT_MESSAGE_RANGE, null, \ + user, "You have disarmed [target]!") else I = null playsound(target, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) @@ -1635,7 +1660,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) playsound(target, 'sound/weapons/punchmiss.ogg', 25, 1, -1) target.visible_message("[user] attempted to disarm [target]!", \ - "[user] attemped to disarm [target]!", null, COMBAT_MESSAGE_RANGE) + "[user] attemped to disarm [target]!", null, COMBAT_MESSAGE_RANGE, null, \ + user, "You attempted to disarm [target]!") log_combat(user, target, "attempted to disarm") @@ -1668,20 +1694,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) disarm(M, H, attacker_style) /datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H) - //CIT CHANGES START HERE - combatmode and resting checks - var/totitemdamage = I.force - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - totitemdamage *= 0.5 - if(!CHECK_MOBILITY(user, MOBILITY_STAND)) - totitemdamage *= 0.5 - if(istype(H)) - if(!(H.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - totitemdamage *= 1.5 - //CIT CHANGES END HERE + var/totitemdamage = H.pre_attacked_by(I, user) // Allows you to put in item-specific reactions based on species if(user != H) var/list/block_return = list() - if(H.run_block(I, I.force, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone, return_list = block_return) & BLOCK_SUCCESS) + if(H.mob_run_block(I, totitemdamage, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone, block_return) & BLOCK_SUCCESS) return 0 totitemdamage = block_calculate_resultant_damage(totitemdamage, block_return) if(H.check_martial_melee_block()) @@ -1704,9 +1721,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.send_item_attack_message(I, user, hit_area) - I.do_stagger_action(H, user) + I.do_stagger_action(H, user, totitemdamage) - if(!I.force) + if(!totitemdamage) return 0 //item force is zero //dismemberment @@ -1735,7 +1752,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 20) if(H.stat == CONSCIOUS) H.visible_message("[H] has been knocked senseless!", \ - "[H] has been knocked senseless!") + "You have been knocked senseless!") H.confused = max(H.confused, 20) H.adjust_blurriness(10) if(prob(10)) @@ -1791,9 +1808,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) return TRUE if(M.mind) attacker_style = M.mind.martial_art - if((M != H) && M.a_intent != INTENT_HELP && (H.run_block(M, 0, "[M]", ATTACK_TYPE_UNARMED, 0, M, M.zone_selected) & BLOCK_SUCCESS)) + if((M != H) && M.a_intent != INTENT_HELP && (H.mob_run_block(M, 0, "[M]", ATTACK_TYPE_UNARMED, 0, M, M.zone_selected, null) & BLOCK_SUCCESS)) log_combat(M, H, "attempted to touch") - H.visible_message("[M] attempted to touch [H]!") + H.visible_message("[M] attempted to touch [H]!", \ + "[M] attempted to touch you!", target = M, \ + target_message = "You attempted to touch [H]!") return TRUE switch(M.a_intent) if(INTENT_HELP) @@ -1830,7 +1849,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) to_chat(user, "You're too exhausted.") return FALSE if(target.check_martial_melee_block()) - target.visible_message("[target] blocks [user]'s shoving attempt!") + target.visible_message("[target] blocks [user]'s shoving attempt!", \ + "You block [user]'s shoving attempt!", target = user, \ + target_message = "[target] blocks your shoving attempt!") return FALSE if(attacker_style && attacker_style.disarm_act(user,target)) return TRUE @@ -1875,19 +1896,22 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/targetatrest = !CHECK_MOBILITY(target, MOBILITY_STAND) if((directional_blocked || !(target_collateral_human || target_shove_turf.shove_act(target, user))) && !targetatrest) target.DefaultCombatKnockdown(SHOVE_KNOCKDOWN_SOLID) - user.visible_message("[user.name] shoves [target.name], knocking them down!", - "You shove [target.name], knocking them down!", null, COMBAT_MESSAGE_RANGE) + target.visible_message("[user.name] shoves [target.name], knocking them down!", + "[user.name] shoves you, knocking you down!", null, COMBAT_MESSAGE_RANGE, null, + user, "You shove [target.name], knocking them down!") log_combat(user, target, "shoved", "knocking them down") else if(target_collateral_human && !targetatrest) target.DefaultCombatKnockdown(SHOVE_KNOCKDOWN_HUMAN) target_collateral_human.DefaultCombatKnockdown(SHOVE_KNOCKDOWN_COLLATERAL) - user.visible_message("[user.name] shoves [target.name] into [target_collateral_human.name]!", - "You shove [target.name] into [target_collateral_human.name]!", null, COMBAT_MESSAGE_RANGE) + target.visible_message("[user.name] shoves [target.name] into [target_collateral_human.name]!", + "[user.name] shoves you into [target_collateral_human.name]!", null, COMBAT_MESSAGE_RANGE, null, + user, "You shove [target.name] into [target_collateral_human.name]!") append_message += ", into [target_collateral_human.name]" else - user.visible_message("[user.name] shoves [target.name]!", - "You shove [target.name]!", null, COMBAT_MESSAGE_RANGE) + target.visible_message("[user.name] shoves [target.name]!", + "[user.name] shoves you!", null, COMBAT_MESSAGE_RANGE, null, + user, "You shove [target.name]!") var/obj/item/target_held_item = target.get_active_held_item() if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types)) target_held_item = null diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm index 559abd8d0b..94f64ceacb 100644 --- a/code/modules/mob/living/carbon/human/species_types/android.dm +++ b/code/modules/mob/living/carbon/human/species_types/android.dm @@ -9,6 +9,7 @@ gib_types = /obj/effect/gibspawner/robot damage_overlay_type = "synth" mutanttongue = /obj/item/organ/tongue/robot + species_language_holder = /datum/language_holder/synthetic limbs_id = "synth" /datum/species/android/on_species_gain(mob/living/carbon/C) diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm index ef730da219..1d19f28aa8 100644 --- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm +++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm @@ -13,6 +13,7 @@ blacklisted = TRUE limbs_id = "human" skinned_type = /obj/item/stack/sheet/animalhide/human + has_field_of_vision = FALSE //Too much of a trouble, their vision is already bound to their severed head. var/pumpkin = FALSE var/obj/item/dullahan_relay/myhead @@ -132,13 +133,13 @@ return INITIALIZE_HINT_QDEL owner = new_owner START_PROCESSING(SSobj, src) - RegisterSignal(owner, COMSIG_CLICK_SHIFT, .proc/examinate_check) + RegisterSignal(owner, COMSIG_MOB_CLICKED_SHIFT_ON, .proc/examinate_check) RegisterSignal(src, COMSIG_ATOM_HEARER_IN_VIEW, .proc/include_owner) RegisterSignal(owner, COMSIG_LIVING_REGENERATE_LIMBS, .proc/unlist_head) RegisterSignal(owner, COMSIG_LIVING_REVIVE, .proc/retrieve_head) -/obj/item/dullahan_relay/proc/examinate_check(atom/source, mob/user) - if(user.client.eye == src) +/obj/item/dullahan_relay/proc/examinate_check(mob/source, atom/target) + if(source.client.eye == src) return COMPONENT_ALLOW_EXAMINATE /obj/item/dullahan_relay/proc/include_owner(datum/source, list/processing_list, list/hearers) diff --git a/code/modules/mob/living/carbon/human/species_types/dwarves.dm b/code/modules/mob/living/carbon/human/species_types/dwarves.dm index 57a973bf22..dfeff24141 100644 --- a/code/modules/mob/living/carbon/human/species_types/dwarves.dm +++ b/code/modules/mob/living/carbon/human/species_types/dwarves.dm @@ -17,6 +17,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) // disliked_food = JUNKFOOD | FRIED //Dwarves hate foods that have no nutrition other than alcohol. mutant_organs = list(/obj/item/organ/dwarfgland) //Dwarven alcohol gland, literal gland warrior mutantliver = /obj/item/organ/liver/dwarf //Dwarven super liver (Otherwise they r doomed) + species_language_holder = /datum/language_holder/dwarf /mob/living/carbon/human/species/dwarf //species admin spawn path race = /datum/species/dwarf //and the race the path is set to. @@ -30,17 +31,14 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) // . = ..() var/dwarf_hair = pick("Beard (Dwarf)", "Beard (Very Long)", "Beard (Long)") //beard roullette var/mob/living/carbon/human/H = C - H.grant_language(/datum/language/dwarf) H.facial_hair_style = dwarf_hair H.update_hair() - H.transform = H.transform.Scale(1, 0.8) //We use scale, and yeah. Dwarves can become gnomes with DWARFISM. + H.AddElement(/datum/element/dwarfism, COMSIG_SPECIES_LOSS, src) RegisterSignal(C, COMSIG_MOB_SAY, .proc/handle_speech) //We register handle_speech is being used. /datum/species/dwarf/on_species_loss(mob/living/carbon/H, datum/species/new_species) . = ..() - H.transform = H.transform.Scale(1, 1.25) //And we undo it. UnregisterSignal(H, COMSIG_MOB_SAY) //We register handle_speech is not being used. - H.remove_language(/datum/language/dwarf) //Dwarf Name stuff /proc/dwarf_name() //hello caller: my name is urist mcuristurister @@ -122,7 +120,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) // return //Filth Reactions - Since miasma now exists var/filth_counter = 0 //Holder for the filth check cycle, basically contains how much filth dwarf sees numerically. - for(var/fuck in view(owner,7)) //hello byond for view loop. + for(var/fuck in owner.fov_view(7)) //hello byond for view loop. if(istype(fuck, /mob/living/carbon/human)) var/mob/living/carbon/human/H = fuck if(H.stat == DEAD || (HAS_TRAIT(H, TRAIT_FAKEDEATH))) diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index 7a5e347060..2b9d28a5f7 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -293,9 +293,7 @@ if(isturf(H.loc)) //else, there's considered to be no light var/turf/T = H.loc light_amount = min(1,T.get_lumcount()) - 0.5 - H.nutrition += light_amount * 10 - if(H.nutrition > NUTRITION_LEVEL_FULL) - H.nutrition = NUTRITION_LEVEL_FULL + H.adjust_nutrition(light_amount * 4, NUTRITION_LEVEL_FULL) if(light_amount > 0.2) //if there's enough light, heal H.heal_overall_damage(1,1) H.adjustToxLoss(-1) diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index 10a29c72c1..db6a1e9560 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -21,20 +21,19 @@ coldmod = 6 // = 3x cold damage heatmod = 0.5 // = 1/4x heat damage burnmod = 0.5 // = 1/2x generic burn damage + species_language_holder = /datum/language_holder/jelly /datum/species/jelly/on_species_loss(mob/living/carbon/C) if(regenerate_limbs) regenerate_limbs.Remove(C) if(slime_change) //CIT CHANGE slime_change.Remove(C) //CIT CHANGE - C.remove_language(/datum/language/slime) C.faction -= "slime" ..() C.faction -= "slime" /datum/species/jelly/on_species_gain(mob/living/carbon/C, datum/species/old_species) ..() - C.grant_language(/datum/language/slime) if(ishuman(C)) regenerate_limbs = new regenerate_limbs.Grant(C) diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 46c37a5b03..196073773b 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -24,9 +24,7 @@ disliked_food = GRAIN | DAIRY liked_food = GROSS | MEAT inert_mutation = FIREBREATH - -/datum/species/lizard/after_equip_job(datum/job/J, mob/living/carbon/human/H) - H.grant_language(/datum/language/draconic) + species_language_holder = /datum/language_holder/lizard /datum/species/lizard/random_name(gender,unique,lastname) if(unique) @@ -86,6 +84,7 @@ mutantlungs = /obj/item/organ/lungs/ashwalker burnmod = 0.9 brutemod = 0.9 + species_language_holder = /datum/language_holder/lizard/ash /datum/species/lizard/ashwalker/on_species_gain(mob/living/carbon/human/C, datum/species/old_species) if((C.dna.features["spines"] != "None" ) && (C.dna.features["tail_lizard"] == "None")) //tbh, it's kinda ugly for them not to have a tail yet have floating spines diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm index 5390d9e7f4..dcb6d868fc 100644 --- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm @@ -23,9 +23,7 @@ mutanteyes = /obj/item/organ/eyes/night_vision/mushroom var/datum/martial_art/mushpunch/mush - -/datum/species/mush/after_equip_job(datum/job/J, mob/living/carbon/human/H) - H.grant_language(/datum/language/mushroom) //pomf pomf + species_language_holder = /datum/language_holder/mushroom /datum/species/mush/on_species_gain(mob/living/carbon/C, datum/species/old_species) . = ..() diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm index 44a794c2ab..817498e417 100644 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm @@ -12,7 +12,8 @@ meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/plant disliked_food = MEAT | DAIRY liked_food = VEGETABLES | FRUIT | GRAIN - var/light_nutrition_gain_factor = 10 + species_language_holder = /datum/language_holder/sylvan + var/light_nutrition_gain_factor = 4 var/light_toxheal = 1 var/light_oxyheal = 1 var/light_burnheal = 1 @@ -35,9 +36,7 @@ if(isturf(H.loc)) //else, there's considered to be no light var/turf/T = H.loc light_amount = min(1,T.get_lumcount()) - 0.5 - H.nutrition += light_amount * light_nutrition_gain_factor - if(H.nutrition >= NUTRITION_LEVEL_FULL) - H.nutrition = NUTRITION_LEVEL_FULL - 1 + H.adjust_nutrition(light_amount * light_nutrition_gain_factor, NUTRITION_LEVEL_FULL) if(light_amount > 0.2) //if there's enough light, heal H.heal_overall_damage(light_bruteheal, light_burnheal) H.adjustToxLoss(-light_toxheal) @@ -69,8 +68,7 @@ H.adjustFireLoss(rand(5,15)) H.show_message("The radiation beam singes you!") if(/obj/item/projectile/energy/florayield) - H.nutrition = min(H.nutrition+30, NUTRITION_LEVEL_FULL) - + H.adjust_nutrition(30, NUTRITION_LEVEL_FULL) /datum/species/pod/pseudo_weak name = "Anthromorphic Plant" @@ -78,7 +76,7 @@ species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS) mutant_bodyparts = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "mam_body_markings" = "Husky", "taur" = "None", "legs" = "Normal Legs") limbs_id = "pod" - light_nutrition_gain_factor = 7.5 + light_nutrition_gain_factor = 3 light_bruteheal = 0.2 light_burnheal = 0.2 light_toxheal = 0.7 diff --git a/code/modules/mob/living/carbon/human/species_types/synths.dm b/code/modules/mob/living/carbon/human/species_types/synths.dm index deab31dec3..85f1fbf386 100644 --- a/code/modules/mob/living/carbon/human/species_types/synths.dm +++ b/code/modules/mob/living/carbon/human/species_types/synths.dm @@ -16,6 +16,7 @@ var/list/initial_inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOLIMBDISABLE,TRAIT_NOHUNGER,TRAIT_NOBREATH) var/disguise_fail_health = 75 //When their health gets to this level their synthflesh partially falls off var/datum/species/fake_species = null //a species to do most of our work for us, unless we're damaged + species_language_holder = /datum/language_holder/synthetic /datum/species/synth/military name = "Military Synth" diff --git a/code/modules/mob/living/carbon/human/status_procs.dm b/code/modules/mob/living/carbon/human/status_procs.dm index 37bafdab67..7892380d8b 100644 --- a/code/modules/mob/living/carbon/human/status_procs.dm +++ b/code/modules/mob/living/carbon/human/status_procs.dm @@ -34,12 +34,11 @@ /mob/living/carbon/human/set_drugginess(amount) ..() if(!amount) - remove_language(/datum/language/beachbum) + remove_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_HIGH) /mob/living/carbon/human/adjust_drugginess(amount) ..() - if(!dna.check_mutation(STONER)) - if(druggy) - grant_language(/datum/language/beachbum) - else - remove_language(/datum/language/beachbum) + if(druggy) + grant_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_HIGH) + else + remove_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_HIGH) diff --git a/code/modules/mob/living/carbon/human/typing_indicator.dm b/code/modules/mob/living/carbon/human/typing_indicator.dm new file mode 100644 index 0000000000..16ed95790a --- /dev/null +++ b/code/modules/mob/living/carbon/human/typing_indicator.dm @@ -0,0 +1,2 @@ +/mob/living/carbon/human/get_typing_indicator_icon_state() + return dna?.species?.typing_indicator_state || ..() diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 00a0991e19..e85769ca12 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -476,7 +476,7 @@ if(SSmobs.times_fired%3==1) if(!(M.status_flags & GODMODE)) M.adjustBruteLoss(5) - nutrition += 10 + adjust_nutrition(10) /* @@ -502,11 +502,23 @@ GLOBAL_LIST_INIT(ballmer_good_msg, list("Hey guys, what if we rolled out a blues "Hear me out here. What if, and this is just a theory, we made R&D controllable from our PDAs?", "I'm thinking we should roll out a git repository for our research under the AGPLv3 license so that we can share it among the other stations freely.", "I dunno about you guys, but IDs and PDAs being separate is clunky as fuck. Maybe we should merge them into a chip in our arms? That way they can't be stolen easily.", - "Why the fuck aren't we just making every pair of shoes into galoshes? We have the technology.")) + "Why the fuck aren't we just making every pair of shoes into galoshes? We have the technology.", + "We can link the Ore Silo to our protolathes, so why don't we also link it to autolathes?", + "If we can make better bombs with heated plasma, oxygen, and tritium, then why do station nukes still use plutonium?", + "We should port all our NT programs to modular consoles and do away with computers. They're way more customizable, support cross-platform usage, and would allow crazy amounts of multitasking.", + "Wait, if we use more manipulators in something, then it prints for cheaper, right? So what if we just made a new type of printer that has like 12 manipulators inside of it to print stuff for really cheap?" + )) GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put a webserver that's automatically turned on with default admin passwords into every PDA?", - "So like, you know how we separate our codebase from the master copy that runs on our consumer boxes? What if we merged the two and undid the separation between codebase and server?", - "Dude, radical idea: H.O.N.K mechs but with no bananium required.", - "Best idea ever: Disposal pipes instead of hallways.")) + "So like, you know how we separate our codebase from the master copy that runs on our consumer boxes? What if we merged the two and undid the separation between codebase and server?", + "Dude, radical idea: H.O.N.K mechs but with no bananium required.", + "Best idea ever: Disposal pipes instead of hallways.", + "What if we use a language that was written on a napkin and created over 1 weekend for all of our servers?", + "What if we took a locker, some random trash, and made an exosuit out of it? Wouldn't that be like, super cool and stuff?", + "Okay, hear me out, what if we make illegal things not illegal, so that sec stops arresting us for having it?", + "I have a crazy idea, guys. Rather than having monkeys to test on, what if we only used apes?", + "Woh man ok, what if we took slime cores and smashed them into other slimes, be kinda cool to see what happens.", + "We're NANOtrasen but we need to unlock nano parts, what's the deal with that?" + )) //this updates all special effects: stun, sleeping, knockdown, druggy, stuttering, etc.. /mob/living/carbon/handle_status_effects() diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 18c3fde188..5b91119789 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -45,6 +45,7 @@ /mob/living/carbon/monkey/ComponentInitialize() . = ..() AddElement(/datum/element/mob_holder, worn_state = "monkey", inv_slots = ITEM_SLOT_HEAD) + AddComponent(/datum/component/footstep, FOOTSTEP_MOB_BAREFOOT, 1, 2) /mob/living/carbon/monkey/Destroy() diff --git a/code/modules/mob/living/carbon/say.dm b/code/modules/mob/living/carbon/say.dm index 30c962f9a5..865a1ac83f 100644 --- a/code/modules/mob/living/carbon/say.dm +++ b/code/modules/mob/living/carbon/say.dm @@ -12,9 +12,9 @@ return 0 return ..() -/mob/living/carbon/could_speak_in_language(datum/language/dt) +/mob/living/carbon/could_speak_language(datum/language/language) var/obj/item/organ/tongue/T = getorganslot(ORGAN_SLOT_TONGUE) if(T) - . = T.could_speak_in_language(dt) + return T.could_speak_language(language) else - . = initial(dt.flags) & TONGUELESS_SPEECH \ No newline at end of file + return initial(language.flags) & TONGUELESS_SPEECH \ No newline at end of file diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index db5771f75e..502ebcbe5d 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -9,10 +9,6 @@ diag_hud.add_to_hud(src) faction += "[REF(src)]" GLOB.mob_living_list += src - initialize_footstep() - -/mob/living/proc/initialize_footstep() - AddComponent(/datum/component/footstep) /mob/living/prepare_huds() ..() @@ -46,7 +42,8 @@ return ..() /mob/living/proc/ZImpactDamage(turf/T, levels) - visible_message("[src] crashes into [T] with a sickening noise!") + visible_message("[src] crashes into [T] with a sickening noise!", \ + "You crash into [T] with a sickening noise!") adjustBruteLoss((levels * 5) ** 1.5) DefaultCombatKnockdown(levels * 50) @@ -124,7 +121,9 @@ to_chat(src, "You're too exhausted to crawl under [L].") return TRUE ENABLE_BITFIELD(combat_flags, COMBAT_FLAG_ATTEMPTING_CRAWL) - visible_message("[src] is attempting to crawl under [L].", "You are now attempting to crawl under [L].") + visible_message("[src] is attempting to crawl under [L].", + "You are now attempting to crawl under [L].", + target = L, target_message = "[src] is attempting to crawl under you.") if(!do_after(src, CRAWLUNDER_DELAY, target = src) || CHECK_MOBILITY(src, MOBILITY_STAND)) DISABLE_BITFIELD(combat_flags, COMBAT_FLAG_ATTEMPTING_CRAWL) return TRUE @@ -276,7 +275,9 @@ if(AM.pulledby) if(!supress_message) - visible_message("[src] has pulled [AM] from [AM.pulledby]'s grip.") + AM.pulledby.visible_message("[src] has pulled [AM] from [AM.pulledby]'s grip.", + "[src] has pulled [AM] from your grip.", target = src, + target_message = "You have pulled [AM] from [AM.pulledby]'s grip.") log_combat(AM, AM.pulledby, "pulled from", src) AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once. @@ -291,7 +292,9 @@ log_combat(src, M, "grabbed", addition="passive grab") if(!supress_message && !(iscarbon(AM) && HAS_TRAIT(src, TRAIT_STRONG_GRABBER))) - visible_message("[src] has grabbed [M][(zone_selected == "l_arm" || zone_selected == "r_arm")? " by their hands":" passively"]!") //Cit change - And they thought ERP was bad. + visible_message("[src] has grabbed [M][(zone_selected == "l_arm" || zone_selected == "r_arm")? " by [M.p_their()] hands":" passively"]!", + "You have grabbed [M][(zone_selected == "l_arm" || zone_selected == "r_arm")? " by [M.p_their()] hands":" passively"]!", target = M, + target_message = "[src] has grabbed you[(zone_selected == "l_arm" || zone_selected == "r_arm")? " by your hands":" passively"]!") if(!iscarbon(src)) M.LAssailant = null else @@ -379,7 +382,7 @@ stop_pulling() //same as above -/mob/living/pointed(atom/A as mob|obj|turf in view()) +/mob/living/pointed(atom/A as mob|obj|turf in fov_view()) if(incapacitated()) return FALSE if(HAS_TRAIT(src, TRAIT_DEATHCOMA)) @@ -563,7 +566,7 @@ SetAllImmobility(0, FALSE) SetSleeping(0, FALSE) radiation = 0 - nutrition = NUTRITION_LEVEL_FED + 50 + set_nutrition(NUTRITION_LEVEL_FED + 50) bodytemperature = BODYTEMP_NORMAL set_blindness(0) set_blurriness(0) @@ -756,12 +759,16 @@ . = ..() if(pulledby.grab_state > GRAB_PASSIVE) if(CHECK_MOBILITY(src, MOBILITY_RESIST) && prob(30/pulledby.grab_state)) - visible_message("[src] has broken free of [pulledby]'s grip!") + pulledby.visible_message("[src] has broken free of [pulledby]'s grip!", + "[src] has broken free of your grip!", target = src, + target_message = "You have broken free of [pulledby]'s grip!") pulledby.stop_pulling() return TRUE else if(moving_resist && client) //we resisted by trying to move // this is a horrible system and whoever thought using client instead of mob is okay is not an okay person client.move_delay = world.time + 20 - visible_message("[src] resists against [pulledby]'s grip!") + pulledby.visible_message("[src] resists against [pulledby]'s grip!", + "[src] resists against your grip!", target = src, + target_message = "You resist against [pulledby]'s grip!") else pulledby.stop_pulling() return TRUE @@ -826,7 +833,8 @@ strip_silence = g.strip_silence if (!strip_silence) who.visible_message("[src] tries to remove [who]'s [what.name].", \ - "[src] tries to remove [who]'s [what.name].") + "[src] tries to remove your [what.name].", target = src, + target_message = "You try to remove [who]'s [what.name].") what.add_fingerprint(src) else to_chat(src,"You try to remove [who]'s [what.name].") @@ -874,7 +882,9 @@ to_chat(src, "\The [what.name] doesn't fit in that place!") return - visible_message("[src] tries to put [what] on [who].") + who.visible_message("[src] tries to put [what] on [who].", + "[src] tries to put [what] on you.", target = src, + target_message = "You try to put [what] on [who].") if(do_mob(src, who, what.equip_delay_other)) if(what && Adjacent(who) && what.mob_can_equip(who, src, final_where, TRUE, TRUE)) if(temporarilyRemoveItemFromInventory(what)) @@ -899,7 +909,7 @@ var/final_pixel_y = get_standard_pixel_y_offset(lying) animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff , time = 2, loop = 6) animate(pixel_x = final_pixel_x , pixel_y = final_pixel_y , time = 2) - setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure to restart it in next life(). + floating_need_update = TRUE /mob/living/proc/get_temperature(datum/gas_mixture/environment) var/loc_temp = environment ? environment.temperature : T0C @@ -1058,7 +1068,7 @@ /mob/living/proc/IgniteMob() if(fire_stacks > 0 && !on_fire) on_fire = 1 - src.visible_message("[src] catches fire!", \ + visible_message("[src] catches fire!", \ "You're set on fire!") new/obj/effect/dummy/lighting_obj/moblight/fire(src) throw_alert("fire", /obj/screen/alert/fire) diff --git a/code/modules/mob/living/living_block.dm b/code/modules/mob/living/living_block.dm index 1efc487f60..e9f1ad70a2 100644 --- a/code/modules/mob/living/living_block.dm +++ b/code/modules/mob/living/living_block.dm @@ -1,12 +1,5 @@ -// This file has a weird name, but it's for anything related to the checks for shields, blocking, dodging, and similar "stop this attack before it actually impacts the target" as opposed to "defend once it has hit". - -///Check whether or not we can block, without "triggering" a block. Basically run checks without effects like depleting shields. Wrapper for do_run_block(). The arguments on that means the same as for this. -/mob/living/proc/check_block(atom/object, damage, attack_text = "the attack", attack_type, armour_penetration, mob/attacker, def_zone, list/return_list, attack_direction) - return do_run_block(FALSE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list, attack_direction) - -/// Runs a block "sequence", effectively checking and then doing effects if necessary. Wrapper for do_run_block(). The arguments on that means the same as for this. -/mob/living/proc/run_block(atom/object, damage, attack_text = "the attack", attack_type, armour_penetration, mob/attacker, def_zone, list/return_list, attack_direction) - return do_run_block(TRUE, object, damage, attack_text, attack_type, armour_penetration, attacker, check_zone(def_zone), return_list, attack_direction) +// This file has a weird name, but it's for anything related to the checks for shields, blocking, dodging, +// and similar "stop this attack before it actually impacts the target" as opposed to "defend once it has hit". /** The actual proc for block checks. DO NOT USE THIS DIRECTLY UNLESS YOU HAVE VERY GOOD REASON TO. To reduce copypaste for differences between handling for real attacks and virtual checks. * Automatically checks all held items for /obj/item/proc/run_block() with the same parameters. @@ -84,7 +77,8 @@ if(. & BLOCK_SUCCESS) return if(prob(final_block_chance)) - owner.visible_message("[owner] blocks [attack_text] with [src]!") + owner.visible_message("[owner] blocks [attack_text] with [src]!", + "You block [attack_text] with [src]!") return . | BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL return . | BLOCK_NONE diff --git a/code/modules/mob/living/living_combat.dm b/code/modules/mob/living/living_combat.dm index 470bba4565..93f61254df 100644 --- a/code/modules/mob/living/living_combat.dm +++ b/code/modules/mob/living/living_combat.dm @@ -17,7 +17,7 @@ update_combat_mode_icon() /mob/living/proc/disable_combat_mode(silent = TRUE, was_forced = FALSE, visible = FALSE, update_icon = TRUE) - if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) || (combat_flags & COMBAT_FLAG_COMBAT_FORCED)) return DISABLE_BITFIELD(combat_flags, COMBAT_FLAG_COMBAT_ACTIVE) SEND_SIGNAL(src, COMSIG_LIVING_COMBAT_DISABLED, was_forced) @@ -61,6 +61,8 @@ /mob/living/proc/disable_intentional_combat_mode(silent = TRUE, visible = FALSE) if(!(combat_flags & COMBAT_FLAG_COMBAT_TOGGLED) && !(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) return + if(combat_flags & COMBAT_FLAG_COMBAT_FORCED) + return DISABLE_BITFIELD(combat_flags, COMBAT_FLAG_COMBAT_TOGGLED) if(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) disable_combat_mode(silent, FALSE, visible, FALSE) @@ -72,6 +74,9 @@ /mob/living/proc/user_toggle_intentional_combat_mode(visible = TRUE) var/old = (combat_flags & COMBAT_FLAG_COMBAT_TOGGLED) if(old) + if(combat_flags & COMBAT_FLAG_COMBAT_FORCED) + to_chat(src, "You are unable to relax your muscles.") + return disable_intentional_combat_mode() playsound_local(src, 'sound/misc/ui_toggleoff.ogg', 50, FALSE, pressure_affected = FALSE) //Slightly modified version of the above! else if(CAN_TOGGLE_COMBAT_MODE(src)) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 1335c8c2dc..02bc88d286 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -43,21 +43,21 @@ P.setAngle(SIMPLIFY_DEGREES(P.Angle + rand(120, 240))) if(!silent) visible_message("[P] gets deflected by [src]!", \ - "[P] gets deflected by [src]!") + "You deflect [P]!") if(REDIRECT_METHOD_REFLECT) P.setAngle(SIMPLIFY_DEGREES(P.Angle + 180)) if(!silent) visible_message("[P] gets reflected by [src]!", \ - "[P] gets reflected by [src]!") + "You reflect [P]!") if(REDIRECT_METHOD_PASSTHROUGH) if(!silent) visible_message("[P] passes through [src]!", \ - "[P] passes through [src]!") + "[P] passes through you!") return if(REDIRECT_METHOD_RETURN_TO_SENDER) if(!silent) visible_message("[src] deflects [P] back at their attacker!", \ - "[src] deflects [P] back at their attacker!") + "You deflect [P] back at your attacker!") if(P.firer) P.setAngle(Get_Angle(src, P.firer)) else @@ -69,7 +69,7 @@ var/totaldamage = P.damage if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself var/list/returnlist = list() - var/returned = run_block(P, P.damage, "the [P.name]", ATTACK_TYPE_PROJECTILE, P.armour_penetration, P.firer, def_zone, returnlist) + var/returned = mob_run_block(P, P.damage, "the [P.name]", ATTACK_TYPE_PROJECTILE, P.armour_penetration, P.firer, def_zone, returnlist) if(returned & BLOCK_SHOULD_REDIRECT) handle_projectile_attack_redirection(P, returnlist[BLOCK_RETURN_REDIRECT_METHOD]) if(returned & BLOCK_REDIRECTED) @@ -115,7 +115,7 @@ var/impacting_zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest var/list/block_return = list() var/total_damage = I.throwforce - if(run_block(AM, throwpower, "\the [AM.name]", ATTACK_TYPE_THROWN, 0, throwingdatum?.thrower, impacting_zone, return_list = block_return) & BLOCK_SUCCESS) + if(mob_run_block(AM, throwpower, "\the [AM.name]", ATTACK_TYPE_THROWN, 0, throwingdatum?.thrower, impacting_zone, block_return) & BLOCK_SUCCESS) hitpush = FALSE skipcatch = TRUE blocked = TRUE @@ -146,7 +146,7 @@ playsound(loc, 'sound/weapons/throwtap.ogg', 1, volume, -1)//...play throwtap.ogg. if(!blocked) visible_message("[src] has been hit by [I].", \ - "[src] has been hit by [I].") + "You have been hit by [I].") var/armor = run_armor_check(impacting_zone, "melee", "Your armor has protected your [parse_zone(impacting_zone)].", "Your armor has softened hit to your [parse_zone(impacting_zone)].",I.armour_penetration) apply_damage(total_damage, dtype, impacting_zone, armor) if(I.thrownby) @@ -180,12 +180,15 @@ return updatehealth() visible_message("[M.name] has hit [src]!", \ - "[M.name] has hit [src]!", null, COMBAT_MESSAGE_RANGE) + "[M.name] has hit you!", null, COMBAT_MESSAGE_RANGE, null, + M.occupant, "You hit [src] with your [M.name]!") log_combat(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])") else step_away(src,M) log_combat(M.occupant, src, "pushed", M) - visible_message("[M] pushes [src] out of the way.", null, null, 5) + visible_message("[M] pushes [src] out of the way.", \ + "[M] pushes you out of the way.", null, COMBAT_MESSAGE_RANGE, null, + M.occupant, "You push [src] out of the way with your [M.name].") /mob/living/fire_act() adjust_fire_stacks(3) @@ -229,7 +232,8 @@ var/old_grab_state = user.grab_state var/grab_upgrade_time = instant ? 0 : 30 visible_message("[user] starts to tighten [user.p_their()] grip on [src]!", \ - "[user] starts to tighten [user.p_their()] grip on you!") + "[user] starts to tighten [user.p_their()] grip on you!", target = user, + target_message = "You start to tighten your grip on [src]!") switch(user.grab_state) if(GRAB_AGGRESSIVE) log_combat(user, src, "attempted to neck grab", addition="neck grab") @@ -247,25 +251,29 @@ var/add_log = "" if(HAS_TRAIT(user, TRAIT_PACIFISM)) visible_message("[user] has firmly gripped [src]!", - "[user] has firmly gripped you!") + "[user] has firmly gripped you!", target = user, + target_message = "You have firmly gripped [src]!") add_log = " (pacifist)" else visible_message("[user] has grabbed [src] aggressively!", \ - "[user] has grabbed you aggressively!") + "[user] has grabbed you aggressively!", target = user, \ + target_message = "You have grabbed [src] aggressively!") update_mobility() stop_pulling() log_combat(user, src, "grabbed", addition="aggressive grab[add_log]") if(GRAB_NECK) log_combat(user, src, "grabbed", addition="neck grab") visible_message("[user] has grabbed [src] by the neck!",\ - "[user] has grabbed you by the neck!") + "[user] has grabbed you by the neck!", target = user, \ + target_message = "You have grabbed [src] by the neck!") update_mobility() //we fall down if(!buckled && !density) Move(user.loc) if(GRAB_KILL) log_combat(user, src, "strangled", addition="kill grab") visible_message("[user] is strangling [src]!", \ - "[user] is strangling you!") + "[user] is strangling you!", target = user, \ + target_message = "You are strangling [src]!") update_mobility() //we fall down if(!buckled && !density) Move(user.loc) @@ -275,9 +283,11 @@ /mob/living/attack_hand(mob/user) ..() //Ignoring parent return value here. SEND_SIGNAL(src, COMSIG_MOB_ATTACK_HAND, user) - if((user != src) && user.a_intent != INTENT_HELP && (run_block(user, 0, user.name, ATTACK_TYPE_UNARMED | ATTACK_TYPE_MELEE, null, user, check_zone(user.zone_selected)) & BLOCK_SUCCESS)) + if((user != src) && user.a_intent != INTENT_HELP && (mob_run_block(user, 0, user.name, ATTACK_TYPE_UNARMED | ATTACK_TYPE_MELEE, null, user, check_zone(user.zone_selected), null) & BLOCK_SUCCESS)) log_combat(user, src, "attempted to touch") - visible_message("[user] attempted to touch [src]!") + visible_message("[user] attempted to touch [src]!", + "[user] attempted to touch you!", target = user, + target_message = "You attempted to touch [src]!") return TRUE /mob/living/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) @@ -286,7 +296,7 @@ to_chat(user, "You don't want to hurt [src]!") return TRUE var/hulk_verb = pick("smash","pummel") - if(user != src && (run_block(user, 15, "the [hulk_verb]ing", ATTACK_TYPE_MELEE, null, user, check_zone(user.zone_selected)) & BLOCK_SUCCESS)) + if(user != src && (mob_run_block(user, 15, "the [hulk_verb]ing", ATTACK_TYPE_MELEE, null, user, check_zone(user.zone_selected), null) & BLOCK_SUCCESS)) return TRUE ..() return FALSE @@ -309,7 +319,7 @@ if(M.is_adult) damage = rand(20, 40) var/list/block_return = list() - if(run_block(M, damage, "the [M.name]", ATTACK_TYPE_MELEE, null, M, check_zone(M.zone_selected), return_list = block_return) & BLOCK_SUCCESS) + if(mob_run_block(M, damage, "the [M.name]", ATTACK_TYPE_MELEE, null, M, check_zone(M.zone_selected), block_return) & BLOCK_SUCCESS) return FALSE damage = block_calculate_resultant_damage(damage, block_return) @@ -317,25 +327,29 @@ log_combat(M, src, "attacked") M.do_attack_animation(src) visible_message("The [M.name] glomps [src]!", \ - "The [M.name] glomps [src]!", null, COMBAT_MESSAGE_RANGE) + "The [M.name] glomps [src]!", null, COMBAT_MESSAGE_RANGE, null, + M, "You glomp [src]!") return TRUE /mob/living/attack_animal(mob/living/simple_animal/M) M.face_atom(src) if(M.melee_damage_upper == 0) - M.visible_message("\The [M] [M.friendly] [src]!") + M.visible_message("\The [M] [M.friendly_verb_continuous] [src]!", + "You [M.friendly_verb_simple] [src]!", target = src, + target_message = "\The [M] [M.friendly_verb_continuous] you!") return FALSE else if(HAS_TRAIT(M, TRAIT_PACIFISM)) to_chat(M, "You don't want to hurt anyone!") return FALSE - if(run_block(M, rand(M.melee_damage_lower, M.melee_damage_upper), "the [M.name]", ATTACK_TYPE_MELEE, M.armour_penetration, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS) + if(mob_run_block(M, rand(M.melee_damage_lower, M.melee_damage_upper), "the [M.name]", ATTACK_TYPE_MELEE, M.armour_penetration, M, check_zone(M.zone_selected), null) & BLOCK_SUCCESS) return FALSE if(M.attack_sound) playsound(loc, M.attack_sound, 50, 1, 1) M.do_attack_animation(src) - visible_message("\The [M] [M.attacktext] [src]!", \ - "\The [M] [M.attacktext] [src]!", null, COMBAT_MESSAGE_RANGE) + visible_message("\The [M] [M.attack_verb_continuous] [src]!", \ + "\The [M] [M.attack_verb_continuous] you!", null, COMBAT_MESSAGE_RANGE, null, + M, "You [M.attack_verb_simple] [src]!") log_combat(M, src, "attacked") return TRUE @@ -347,51 +361,60 @@ if(M.is_muzzled() || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH)) to_chat(M, "You can't bite with your mouth covered!") return FALSE - if(run_block(M, 0, "the [M.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS) + if(mob_run_block(M, 0, "the [M.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, 0, M, check_zone(M.zone_selected), null) & BLOCK_SUCCESS) return FALSE M.do_attack_animation(src, ATTACK_EFFECT_BITE) if (prob(75)) log_combat(M, src, "attacked") playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) visible_message("[M.name] bites [src]!", \ - "[M.name] bites [src]!", null, COMBAT_MESSAGE_RANGE) + "[M.name] bites you!", null, COMBAT_MESSAGE_RANGE, null, + M, "You bite [src]!") return TRUE else visible_message("[M.name] has attempted to bite [src]!", \ - "[M.name] has attempted to bite [src]!", null, COMBAT_MESSAGE_RANGE) + "[M.name] has attempted to bite [src]!", null, COMBAT_MESSAGE_RANGE, null, + M, "You have attempted to bite [src]!") return FALSE /mob/living/attack_larva(mob/living/carbon/alien/larva/L) switch(L.a_intent) if(INTENT_HELP) - visible_message("[L.name] rubs its head against [src].") + visible_message("[L.name] rubs its head against [src].", + "[L.name] rubs its head against you.", target = L, \ + target_message = "You rub your head against [src].") return FALSE else if(HAS_TRAIT(L, TRAIT_PACIFISM)) to_chat(L, "You don't want to hurt anyone!") return FALSE - if(L != src && (run_block(L, rand(1, 3), "the [L.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, L, check_zone(L.zone_selected)) & BLOCK_SUCCESS)) + if(L != src && (mob_run_block(L, rand(1, 3), "the [L.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, 0, L, check_zone(L.zone_selected), null) & BLOCK_SUCCESS)) return FALSE L.do_attack_animation(src) if(prob(90)) log_combat(L, src, "attacked") visible_message("[L.name] bites [src]!", \ - "[L.name] bites [src]!", null, COMBAT_MESSAGE_RANGE) + "[L.name] bites you!", null, COMBAT_MESSAGE_RANGE, null, L, \ + "You bite [src]!") playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) return TRUE else visible_message("[L.name] has attempted to bite [src]!", \ - "[L.name] has attempted to bite [src]!", null, COMBAT_MESSAGE_RANGE) + "[L.name] has attempted to bite you!", null, COMBAT_MESSAGE_RANGE, null, L, \ + "You have attempted to bite [src]!") /mob/living/attack_alien(mob/living/carbon/alien/humanoid/M) - if((M != src) && M.a_intent != INTENT_HELP && (run_block(M, 0, "the [M.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, M, check_zone(M.zone_selected)) & BLOCK_SUCCESS)) - visible_message("[M] attempted to touch [src]!") + if((M != src) && M.a_intent != INTENT_HELP && (mob_run_block(M, 0, "the [M.name]", ATTACK_TYPE_MELEE | ATTACK_TYPE_UNARMED, 0, M, check_zone(M.zone_selected), null) & BLOCK_SUCCESS)) + visible_message("[M] attempted to touch [src]!", + "[M] attempted to touch you!") return FALSE switch(M.a_intent) if (INTENT_HELP) if(!isalien(src)) //I know it's ugly, but the alien vs alien attack_alien behaviour is a bit different. - visible_message("[M] caresses [src] with its scythe like arm.") + visible_message("[M] caresses [src] with its scythe like arm.", + "[M] caresses you with its scythe like arm.", target = M, + target_message = "You caress [src] with your scythe like arm.") return FALSE if (INTENT_GRAB) grabbedby(M) @@ -419,21 +442,26 @@ take_bodypart_damage(acidpwr * min(1, acid_volume * 0.1)) return 1 +///As the name suggests, this should be called to apply electric shocks. /mob/living/proc/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE) SEND_SIGNAL(src, COMSIG_LIVING_ELECTROCUTE_ACT, shock_damage, source, siemens_coeff, flags) - if((flags & SHOCK_TESLA) && (flags_1 & TESLA_IGNORE_1)) + shock_damage *= siemens_coeff + if((flags & SHOCK_TESLA) && HAS_TRAIT(src, TRAIT_TESLA_SHOCKIMMUNE)) return FALSE if(HAS_TRAIT(src, TRAIT_SHOCKIMMUNE)) return FALSE - if(shock_damage > 0) - if(!(flags & SHOCK_ILLUSION)) - adjustFireLoss(shock_damage) - visible_message( - "[src] was shocked by \the [source]!", \ - "You feel a powerful shock coursing through your body!", \ - "You hear a heavy electrical crack." \ - ) - return shock_damage + if(shock_damage < 1) + return FALSE + if(!(flags & SHOCK_ILLUSION)) + adjustFireLoss(shock_damage) + else + adjustStaminaLoss(shock_damage) + visible_message( + "[src] was shocked by \the [source]!", \ + "You feel a powerful shock coursing through your body!", \ + "You hear a heavy electrical crack." \ + ) + return shock_damage /mob/living/emp_act(severity) . = ..() @@ -512,4 +540,11 @@ if(!used_item) used_item = get_active_held_item() ..() - setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement. + floating_need_update = TRUE + + +/mob/living/proc/getBruteLoss_nonProsthetic() + return getBruteLoss() + +/mob/living/proc/getFireLoss_nonProsthetic() + return getFireLoss() diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 0b4be7d463..f8abf94083 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -4,6 +4,9 @@ see_in_dark = 2 hud_possible = list(HEALTH_HUD,STATUS_HUD,ANTAG_HUD,NANITE_HUD,DIAG_NANITE_FULL_HUD,RAD_HUD) pressure_resistance = 10 + has_field_of_vision = TRUE + + typing_indicator_enabled = TRUE var/resize = 1 //Badminnery resize var/lastattacker = null @@ -98,8 +101,6 @@ var/datum/riding/riding_datum - var/datum/language/selected_default_language - var/last_words //used for database logging var/list/obj/effect/proc_holder/abilities = list() diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm index 6a84162ea8..4b90191dcc 100644 --- a/code/modules/mob/living/living_movement.dm +++ b/code/modules/mob/living/living_movement.dm @@ -1,6 +1,8 @@ /mob/living/Moved() . = ..() update_turf_movespeed(loc) + //Hide typing indicator if we move. + clear_typing_indicator() if(is_shifted) is_shifted = FALSE pixel_x = get_standard_pixel_x_offset(lying) diff --git a/code/modules/mob/living/living_sprint.dm b/code/modules/mob/living/living_sprint.dm index 55d5f3320c..dc0f6d2767 100644 --- a/code/modules/mob/living/living_sprint.dm +++ b/code/modules/mob/living/living_sprint.dm @@ -33,7 +33,7 @@ update_sprint_icon() /mob/living/proc/disable_sprint_mode(update_icon = TRUE) - if(!(combat_flags & COMBAT_FLAG_SPRINT_ACTIVE)) + if(!(combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) || (combat_flags & COMBAT_FLAG_SPRINT_FORCED)) return DISABLE_BITFIELD(combat_flags, COMBAT_FLAG_SPRINT_ACTIVE) if(update_icon) @@ -51,6 +51,8 @@ /mob/living/proc/disable_intentional_sprint_mode() if(!(combat_flags & COMBAT_FLAG_SPRINT_TOGGLED) && !(combat_flags & COMBAT_FLAG_SPRINT_ACTIVE)) return + if(combat_flags & COMBAT_FLAG_SPRINT_FORCED) + return DISABLE_BITFIELD(combat_flags, COMBAT_FLAG_SPRINT_TOGGLED) if(combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) disable_sprint_mode(FALSE) @@ -59,6 +61,9 @@ /mob/living/proc/user_toggle_intentional_sprint_mode() var/old = (combat_flags & COMBAT_FLAG_SPRINT_TOGGLED) if(old) + if(combat_flags & COMBAT_FLAG_SPRINT_FORCED) + to_chat(src, "You are unable to stop sprinting!") + return disable_intentional_sprint_mode() if((m_intent == MOVE_INTENT_RUN) && CHECK_ALL_MOBILITY(src, MOBILITY_STAND|MOBILITY_MOVE)) playsound_local(src, 'sound/misc/sprintdeactivate.ogg', 50, FALSE, pressure_affected = FALSE) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index a772f4a278..6caf96fedc 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -133,7 +133,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( var/datum/language/message_language = get_message_language(message) if(message_language) // No, you cannot speak in xenocommon just because you know the key - if(can_speak_in_language(message_language)) + if(can_speak_language(message_language)) language = message_language message = copytext_char(message, 3) @@ -141,7 +141,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( message = trim_left(message) if(!language) - language = get_default_language() + language = get_selected_language() // Detection of language needs to be before inherent channels, because // AIs use inherent channels for the holopad. Most inherent channels @@ -415,11 +415,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( /mob/living/whisper(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) say("#[message]", bubble_type, spans, sanitize, language, ignore_spam, forced) -/mob/living/get_language_holder(shadow=TRUE) - if(mind && shadow) - // Mind language holders shadow mob holders. - . = mind.get_language_holder() - if(.) - return . - +/mob/living/get_language_holder(get_minds = TRUE) + if(get_minds && mind) + return mind.get_language_holder() . = ..() diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index dff5584617..4e3093dda2 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -28,6 +28,7 @@ sec_hud = DATA_HUD_SECURITY_BASIC d_hud = DATA_HUD_DIAGNOSTIC_ADVANCED mob_size = MOB_SIZE_LARGE + has_field_of_vision = FALSE //Vision through cameras. var/list/network = list("ss13") var/obj/machinery/camera/current var/list/connected_robots = list() @@ -868,30 +869,33 @@ light_cameras() if(istype(A, /obj/machinery/camera)) current = A - if(client) - if(ismovable(A)) - if(A != GLOB.ai_camera_room_landmark) - end_multicam() - client.perspective = EYE_PERSPECTIVE - client.eye = A - else + if(!client) + return + if(ismovable(A)) + if(A != GLOB.ai_camera_room_landmark) end_multicam() - if(isturf(loc)) - if(eyeobj) - client.eye = eyeobj - client.perspective = EYE_PERSPECTIVE - else - client.eye = client.mob - client.perspective = MOB_PERSPECTIVE - else + client.perspective = EYE_PERSPECTIVE + client.eye = A + else + end_multicam() + if(isturf(loc)) + if(eyeobj) + client.eye = eyeobj client.perspective = EYE_PERSPECTIVE - client.eye = loc - update_sight() - if(client.eye != src) - var/atom/AT = client.eye - AT.get_remote_view_fullscreens(src) + else + client.eye = client.mob + client.perspective = MOB_PERSPECTIVE else - clear_fullscreen("remote_view", 0) + client.perspective = EYE_PERSPECTIVE + client.eye = loc + update_sight() + if(client.eye != src) + var/atom/AT = client.eye + AT.get_remote_view_fullscreens(src) + else + clear_fullscreen("remote_view", 0) + SEND_SIGNAL(src, COMSIG_MOB_RESET_PERSPECTIVE, A) + return TRUE /mob/living/silicon/ai/revive(full_heal = 0, admin_revive = 0) . = ..() diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm index 4a76eafc53..2b5d3d98f2 100644 --- a/code/modules/mob/living/silicon/ai/say.dm +++ b/code/modules/mob/living/silicon/ai/say.dm @@ -171,10 +171,3 @@ #undef VOX_DELAY #endif - -/mob/living/silicon/ai/could_speak_in_language(datum/language/dt) - if(is_servant_of_ratvar(src)) - // Ratvarian AIs can only speak Ratvarian - . = ispath(dt, /datum/language/ratvar) - else - . = ..() diff --git a/code/modules/mob/living/silicon/pai/pai_defense.dm b/code/modules/mob/living/silicon/pai/pai_defense.dm index ba162ecf2c..dcb7ac66c9 100644 --- a/code/modules/mob/living/silicon/pai/pai_defense.dm +++ b/code/modules/mob/living/silicon/pai/pai_defense.dm @@ -32,22 +32,28 @@ /mob/living/silicon/pai/attack_hand(mob/living/carbon/human/user) switch(user.a_intent) if(INTENT_HELP) - visible_message("[user] gently pats [src] on the head, eliciting an off-putting buzzing from its holographic field.") + visible_message("[user] gently pats [src] on the head, eliciting an off-putting buzzing from its holographic field.", + "[user] gently pats you on the head, eliciting an off-putting buzzing from your holographic field.", target = user, + target_message = "You gently pat [src] on the head, eliciting an off-putting buzzing from its holographic field.") if(INTENT_DISARM) - visible_message("[user] boops [src] on the head!") + visible_message("[user] boops [src] on the head!", + "[user] boops you on the head!", target = user, + target_message = "You boop [src] on the head!") if(INTENT_HARM) user.do_attack_animation(src) if (user.name == master) visible_message("Responding to its master's touch, [src] disengages its holochassis emitter, rapidly losing coherence.") - spawn(10) - fold_in() - if(user.put_in_hands(card)) - user.visible_message("[user] promptly scoops up [user.p_their()] pAI's card.") + fold_in() + if(user.put_in_hands(card)) + user.visible_message("[user] promptly scoops up [user.p_their()] pAI's card.", + "You promptly scoops up your pAI's card.") else if(HAS_TRAIT(user, TRAIT_PACIFISM)) to_chat(user, "You don't want to hurt [src]!") return - visible_message("[user] stomps on [src]!.") + visible_message("[user] stomps on [src]!.", + "[user] stomps on you!.", target = user, + target_message = "You stomp on [src]!.") take_holo_damage(2) else grabbedby(user) diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 892cc3f13b..76ced767e8 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -267,9 +267,8 @@ if(href_list["toggle"]) encryptmod = TRUE if("translator") - if(href_list["toggle"]) - grant_all_languages(TRUE) - // this is PERMAMENT. + if(href_list["toggle"]) //This is permanent. + grant_all_languages(TRUE, TRUE, TRUE, LANGUAGE_SOFTWARE) if("doorjack") if(href_list["jack"]) if(cable && cable.machine) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index b389e386d4..633135b3d2 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -3,122 +3,7 @@ real_name = "Cyborg" icon = 'icons/mob/robots.dmi' icon_state = "robot" - maxHealth = 100 - health = 100 bubble_icon = "robot" - designation = "Default" //used for displaying the prefix & getting the current module of cyborg - has_limbs = 1 - hud_type = /datum/hud/robot - - blocks_emissive = EMISSIVE_BLOCK_UNIQUE - - var/custom_name = "" - var/braintype = "Cyborg" - var/obj/item/robot_suit/robot_suit = null //Used for deconstruction to remember what the borg was constructed out of.. - var/obj/item/mmi/mmi = null - - var/shell = FALSE - var/deployed = FALSE - var/mob/living/silicon/ai/mainframe = null - var/datum/action/innate/undeployment/undeployment_action = new - -//Hud stuff - - var/obj/screen/inv1 = null - var/obj/screen/inv2 = null - var/obj/screen/inv3 = null - var/obj/screen/lamp_button = null - var/obj/screen/thruster_button = null - var/obj/screen/hands = null - - var/shown_robot_modules = 0 //Used to determine whether they have the module menu shown or not - var/obj/screen/robot_modules_background - -//3 Modules can be activated at any one time. - var/obj/item/robot_module/module = null - var/obj/item/module_active = null - held_items = list(null, null, null) //we use held_items for the module holding, because that makes sense to do! - - var/mutable_appearance/eye_lights - - var/mob/living/silicon/ai/connected_ai = null - var/obj/item/stock_parts/cell/cell = null - - var/opened = 0 - var/emagged = FALSE - var/emag_cooldown = 0 - var/wiresexposed = 0 - - var/ident = 0 - var/locked = TRUE - var/list/req_access = list(ACCESS_ROBOTICS) - - var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list(), "Burglar"=list()) - - var/speed = 0 // VTEC speed boost. - var/magpulse = FALSE // Magboot-like effect. - var/ionpulse = FALSE // Jetpack-like effect. - var/ionpulse_on = FALSE // Jetpack-like effect. - var/datum/effect_system/trail_follow/ion/ion_trail // Ionpulse effect. - - var/low_power_mode = 0 //whether the robot has no charge left. - var/datum/effect_system/spark_spread/spark_system // So they can initialize sparks whenever/N - - var/lawupdate = 1 //Cyborgs will sync their laws with their AI by default - var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them. - var/locked_down //Boolean of whether the borg is locked down or not - - var/toner = 0 - var/tonermax = 40 - - var/lamp_max = 10 //Maximum brightness of a borg lamp. Set as a var for easy adjusting. - var/lamp_intensity = 0 //Luminosity of the headlamp. 0 is off. Higher settings than the minimum require power. - light_color = "#FFCC66" - light_power = 0.8 - var/lamp_cooldown = 0 //Flag for if the lamp is on cooldown after being forcibly disabled. - - var/sight_mode = 0 - hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_TRACK_HUD) - - var/list/upgrades = list() - - var/hasExpanded = FALSE - var/obj/item/hat - var/hat_offset = -3 - var/list/equippable_hats = list(/obj/item/clothing/head/caphat, - /obj/item/clothing/head/hardhat, - /obj/item/clothing/head/centhat, - /obj/item/clothing/head/HoS, - /obj/item/clothing/head/beret, - /obj/item/clothing/head/kitty, - /obj/item/clothing/head/hopcap, - /obj/item/clothing/head/wizard, - /obj/item/clothing/head/nursehat, - /obj/item/clothing/head/sombrero, - /obj/item/clothing/head/helmet/chaplain/witchunter_hat, - /obj/item/clothing/head/soft/, //All baseball caps - /obj/item/clothing/head/that, //top hat - /obj/item/clothing/head/collectable/tophat, //Not sure where this one is found, but it looks the same so might as well include - /obj/item/clothing/mask/bandana/, //All bandanas (which only work in hat mode) - /obj/item/clothing/head/fedora, - /obj/item/clothing/head/beanie/, //All beanies - /obj/item/clothing/ears/headphones, - /obj/item/clothing/head/helmet/skull, - /obj/item/clothing/head/crown/fancy) - - can_buckle = TRUE - buckle_lying = FALSE - var/static/list/can_ride_typecache = typecacheof(/mob/living/carbon/human) - - var/sitting = 0 - var/bellyup = 0 - var/dogborg = FALSE - - var/cansprint = 1 - - var/orebox = null - -/mob/living/silicon/robot /mob/living/silicon/robot/get_cell() return cell @@ -129,7 +14,7 @@ spark_system.attach(src) wires = new /datum/wires/robot(src) - AddComponent(/datum/component/empprotection, EMP_PROTECT_WIRES) + AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES) robot_modules_background = new() robot_modules_background.icon_state = "block" @@ -427,24 +312,23 @@ else if(istype(W, /obj/item/stack/cable_coil) && wiresexposed) user.changeNext_move(CLICK_CD_MELEE) - var/obj/item/stack/cable_coil/coil = W if (getFireLoss() > 0 || getToxLoss() > 0) - if(src == user && coil.use(1)) + if(src == user) to_chat(user, "You start fixing yourself...") - if(!do_after(user, 50, target = src)) + if(!W.use_tool(src, user, 50, 1, max_level = JOB_SKILL_TRAINED)) + to_chat(user, "You need more cable to repair [src]!") return adjustFireLoss(-10) adjustToxLoss(-10) - if (coil.use(1)) + else to_chat(user, "You start fixing [src]...") - if(!do_after(user, 30, target = src)) + if(!W.use_tool(src, user, 30, 1)) + to_chat(user, "You need more cable to repair [src]!") return adjustFireLoss(-30) adjustToxLoss(-30) updatehealth() user.visible_message("[user] has fixed some of the burnt wires on [src].", "You fix some of the burnt wires on [src].") - else - to_chat(user, "You need more cable to repair [src]!") else to_chat(user, "The wires seem fine, there's no need to fix them.") diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index 5750543a92..e337618e4b 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -32,15 +32,17 @@ var/obj/item/I = get_active_held_item() if(I) uneq_active() - visible_message("[M] disarmed [src]!", \ - "[M] has disabled [src]'s active module!", null, COMBAT_MESSAGE_RANGE) + visible_message("[M] has disarmed [src]!", \ + "[M] has disabled your active module!", null, COMBAT_MESSAGE_RANGE, null, M, + "You have disarmed [src]!") log_combat(M, src, "disarmed", "[I ? " removing \the [I]" : ""]") else Paralyze(40) step(src,get_dir(M,src)) log_combat(M, src, "pushed") visible_message("[M] has forced back [src]!", \ - "[M] has forced back [src]!", null, COMBAT_MESSAGE_RANGE) + "[M] has forced you back!", null, COMBAT_MESSAGE_RANGE, null, M, + "You have forced back [src]!") playsound(loc, 'sound/weapons/pierce.ogg', 50, 1, -1) /mob/living/silicon/robot/attack_slime(mob/living/simple_animal/slime/M) diff --git a/code/modules/mob/living/silicon/robot/robot_defines.dm b/code/modules/mob/living/silicon/robot/robot_defines.dm new file mode 100644 index 0000000000..860d531608 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/robot_defines.dm @@ -0,0 +1,123 @@ + +/mob/living/silicon/robot + designation = "Default" //used for displaying the prefix & getting the current module of cyborg + has_limbs = TRUE + hud_type = /datum/hud/robot + + blocks_emissive = EMISSIVE_BLOCK_UNIQUE + + maxHealth = 100 + health = 100 + + var/custom_name = "" + var/braintype = "Cyborg" + var/obj/item/robot_suit/robot_suit = null //Used for deconstruction to remember what the borg was constructed out of.. + var/obj/item/mmi/mmi = null + + var/shell = FALSE + var/deployed = FALSE + var/mob/living/silicon/ai/mainframe = null + var/datum/action/innate/undeployment/undeployment_action = new + +//Hud stuff + + var/obj/screen/inv1 = null + var/obj/screen/inv2 = null + var/obj/screen/inv3 = null + var/obj/screen/lamp_button = null + var/obj/screen/thruster_button = null + var/obj/screen/hands = null + + var/shown_robot_modules = 0 //Used to determine whether they have the module menu shown or not + var/obj/screen/robot_modules_background + +//3 Modules can be activated at any one time. + var/obj/item/robot_module/module = null + var/obj/item/module_active = null + held_items = list(null, null, null) //we use held_items for the module holding, because that makes sense to do! + + var/mutable_appearance/eye_lights + + var/mob/living/silicon/ai/connected_ai = null + var/obj/item/stock_parts/cell/cell = null + + var/opened = 0 + var/emagged = FALSE + var/emag_cooldown = 0 + var/wiresexposed = 0 + + var/ident = 0 + var/locked = TRUE + var/list/req_access = list(ACCESS_ROBOTICS) + + var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list(), "Burglar"=list()) + + var/speed = 0 // VTEC speed boost. + var/magpulse = FALSE // Magboot-like effect. + var/ionpulse = FALSE // Jetpack-like effect. + var/ionpulse_on = FALSE // Jetpack-like effect. + var/datum/effect_system/trail_follow/ion/ion_trail // Ionpulse effect. + + var/low_power_mode = 0 //whether the robot has no charge left. + var/datum/effect_system/spark_spread/spark_system // So they can initialize sparks whenever/N + + var/lawupdate = 1 //Cyborgs will sync their laws with their AI by default + var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them. + var/locked_down //Boolean of whether the borg is locked down or not + + var/toner = 0 + var/tonermax = 40 + + var/lamp_max = 10 //Maximum brightness of a borg lamp. Set as a var for easy adjusting. + var/lamp_intensity = 0 //Luminosity of the headlamp. 0 is off. Higher settings than the minimum require power. + light_color = "#FFCC66" + light_power = 0.8 + var/lamp_cooldown = 0 //Flag for if the lamp is on cooldown after being forcibly disabled. + + var/sight_mode = 0 + hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_TRACK_HUD) + + var/list/upgrades = list() + + var/hasExpanded = FALSE + var/obj/item/hat + var/hat_offset = -3 + var/list/equippable_hats = list(/obj/item/clothing/head/caphat, + /obj/item/clothing/head/hardhat, + /obj/item/clothing/head/centhat, + /obj/item/clothing/head/HoS, + /obj/item/clothing/head/beret, + /obj/item/clothing/head/kitty, + /obj/item/clothing/head/hopcap, + /obj/item/clothing/head/wizard, + /obj/item/clothing/head/nursehat, + /obj/item/clothing/head/sombrero, + /obj/item/clothing/head/helmet/chaplain/witchunter_hat, + /obj/item/clothing/head/soft/, //All baseball caps + /obj/item/clothing/head/that, //top hat + /obj/item/clothing/head/collectable/tophat, //Not sure where this one is found, but it looks the same so might as well include + /obj/item/clothing/mask/bandana/, //All bandanas (which only work in hat mode) + /obj/item/clothing/head/fedora, + /obj/item/clothing/head/beanie/, //All beanies + /obj/item/clothing/ears/headphones, + /obj/item/clothing/head/helmet/skull, + /obj/item/clothing/head/crown/fancy) + + can_buckle = TRUE + buckle_lying = FALSE + var/static/list/can_ride_typecache = typecacheof(/mob/living/carbon/human) + + var/sitting = 0 + var/bellyup = 0 + var/dogborg = FALSE + + var/cansprint = 1 + + var/orebox = null + + //doggie borg stuff. + var/disabler + var/laser + var/sleeper_g + var/sleeper_r + var/sleeper_nv \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 4659c907a6..bf693d70b6 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -276,6 +276,19 @@ R.hud_used.update_robot_modules_display() SSblackbox.record_feedback("tally", "cyborg_modules", 1, R.module) +/** + * check_menu: Checks if we are allowed to interact with a radial menu + * + * Arguments: + * * user The mob interacting with a menu + */ +/obj/item/robot_module/proc/check_menu(mob/user) + if(!istype(user)) + return FALSE + if(user.incapacitated() || !user.Adjacent(src)) + return FALSE + return TRUE + /obj/item/robot_module/standard name = "Standard" basic_modules = list( @@ -337,13 +350,28 @@ /obj/item/robot_module/medical/be_transformed_to(obj/item/robot_module/old_module) var/mob/living/silicon/robot/R = loc - var/medmodels = list("Default", "Heavy", "Sleek", "Marina", "Droid", "Eyebot", "Medihound", "Medihound Dark", "Vale") - if(R.client && (R.client.ckey in list("nezuli"))) - medmodels += "Alina" - var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in medmodels - if(!borg_icon) - return FALSE - switch(borg_icon) + var/static/list/med_icons + if(!med_icons) + med_icons = list( + "Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "medical"), + "Droid" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "medical"), + "Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekmed"), + "Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinamed"), + "Eyebot" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "eyebotmed"), + "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymed") + ) + var/list/L = list("Medihound" = "medihound", "Medihound Dark" = "medihounddark", "Vale" = "valemed") + for(var/a in L) + var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a]) + wide.pixel_x = -16 + med_icons[a] = wide + if(R.client && R.client.ckey == "nezuli") + var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-med") + bad_snowflake.pixel_x = -16 + med_icons["Alina"] = bad_snowflake + med_icons = sortList(med_icons) + var/med_borg_icon = show_radial_menu(R, R , med_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE) + switch(med_borg_icon) if("Default") cyborg_base_icon = "medical" if("Droid") @@ -391,6 +419,8 @@ moduleselect_icon = "medihound" moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi' dogborg = TRUE + else + return FALSE return ..() /obj/item/robot_module/engineering @@ -434,13 +464,31 @@ /obj/item/robot_module/engineering/be_transformed_to(obj/item/robot_module/old_module) var/mob/living/silicon/robot/R = loc - var/list/engymodels = list("Default", "Default - Treads", "Heavy", "Sleek", "Marina", "Can", "Spider", "Loader","Handy", "Pup Dozer", "Vale") - if(R.client && (R.client.ckey in list("nezuli"))) - engymodels += "Alina" - var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in engymodels - if(!borg_icon) - return FALSE - switch(borg_icon) + var/static/list/engi_icons + if(!engi_icons) + engi_icons = list( + "Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "engineer"), + "Default - Treads" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "engi-tread"), + "Loader" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "loaderborg"), + "Handy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "handyeng"), + "Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekeng"), + "Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "caneng"), + "Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinaeng"), + "Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "spidereng"), + "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyeng") + ) + var/list/L = list("Pup Dozer" = "pupdozer", "Vale" = "valeeng") + for(var/a in L) + var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a]) + wide.pixel_x = -16 + engi_icons[a] = wide + if(R.client && R.client.ckey == "nezuli") + var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-eng") + bad_snowflake.pixel_x = -16 + engi_icons["Alina"] = bad_snowflake + engi_icons = sortList(engi_icons) + var/engi_borg_icon = show_radial_menu(R, R , engi_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE) + switch(engi_borg_icon) if("Default") cyborg_base_icon = "engineer" if("Default - Treads") @@ -485,6 +533,8 @@ cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi' sleeper_overlay = "alinasleeper" dogborg = TRUE + else + return FALSE return ..() /obj/item/robot_module/security @@ -512,13 +562,29 @@ /obj/item/robot_module/security/be_transformed_to(obj/item/robot_module/old_module) var/mob/living/silicon/robot/R = loc - var/list/secmodels = list("Default", "Default - Treads", "Heavy", "Sleek", "Can", "Marina", "Spider", "K9", "K9 Dark", "Vale") - if(R.client && (R.client.ckey in list("nezuli"))) - secmodels += "Alina" - var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in secmodels - if(!borg_icon) - return FALSE - switch(borg_icon) + var/static/list/sec_icons + if(!sec_icons) + sec_icons = list( + "Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "sec"), + "Default - Treads" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sec-tread"), + "Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleeksec"), + "Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "cansec"), + "Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinasec"), + "Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "spidersec"), + "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavysec") + ) + var/list/L = list("K9" = "k9", "Vale" = "valesec", "K9 Dark" = "k9dark") + for(var/a in L) + var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a]) + wide.pixel_x = -16 + sec_icons[a] = wide + if(R.client && R.client.ckey == "nezuli") + var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-sec") + bad_snowflake.pixel_x = -16 + sec_icons["Alina"] = bad_snowflake + sec_icons = sortList(sec_icons) + var/sec_borg_icon = show_radial_menu(R, R , sec_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE) + switch(sec_borg_icon) if("Default") cyborg_base_icon = "sec" if("Default - Treads") @@ -561,6 +627,8 @@ sleeper_overlay = "valesecsleeper" cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi' dogborg = TRUE + else + return FALSE return ..() /obj/item/robot_module/security/Initialize() @@ -599,10 +667,13 @@ /obj/item/robot_module/peacekeeper/be_transformed_to(obj/item/robot_module/old_module) var/mob/living/silicon/robot/R = loc - var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Default", "Spider", "Borgi") - if(!borg_icon) - return FALSE - switch(borg_icon) + var/static/list/peace_icons = sortList(list( + "Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "peace"), + "Borgi" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "borgi"), + "Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "whitespider") + )) + var/peace_borg_icon = show_radial_menu(R, R , peace_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE) + switch(peace_borg_icon) if("Default") cyborg_base_icon = "peace" if("Spider") @@ -615,6 +686,8 @@ hat_offset = INFINITY cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' has_snowflake_deadsprite = TRUE + else + return FALSE return ..() //Janitor module combined with Service module @@ -696,9 +769,9 @@ /obj/item/toy/crayon/spraycan/borg, /obj/item/hand_labeler/borg, /obj/item/razor, + /obj/item/rsf, /obj/item/instrument/violin, /obj/item/instrument/guitar, - /obj/item/rsf/cyborg, /obj/item/reagent_containers/dropper, /obj/item/lighter, /obj/item/storage/bag/tray, @@ -738,10 +811,35 @@ /obj/item/robot_module/butler/be_transformed_to(obj/item/robot_module/old_module) var/mob/living/silicon/robot/R = loc - var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("(Service) Waitress", "(Service) Heavy", "(Service) Sleek", "(Service) Butler", "(Service) Tophat", "(Service) Can", "(Service) Bro", "(Service) DarkK9", "(Service) Vale", "(Service) ValeDark", "(Janitor) Default", "(Janitor) Sleek", "(Janitor) Marina", "(Janitor) Can", "(Janitor) Heavy", "(Janitor) Scrubpuppy") - if(!borg_icon) - return FALSE - switch(borg_icon) + var/static/list/service_icons + if(!service_icons) + service_icons = list( + "(Service) Waitress" = image(icon = 'icons/mob/robots.dmi', icon_state = "service_f"), + "(Service) Butler" = image(icon = 'icons/mob/robots.dmi', icon_state = "service_m"), + "(Service) Bro" = image(icon = 'icons/mob/robots.dmi', icon_state = "brobot"), + "(Service) Can" = image(icon = 'icons/mob/robots.dmi', icon_state = "kent"), + "(Service) Tophat" = image(icon = 'icons/mob/robots.dmi', icon_state = "tophat"), + "(Service) Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekserv"), + "(Service) Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyserv"), + "(Janitor) Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "janitor"), + "(Janitor) Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinajan"), + "(Janitor) Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekjan"), + "(Janitor) Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "canjan"), + "(Janitor) Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyjan"), + ) + var/list/L = list("(Service) DarkK9" = "k50", "(Service) Vale" = "valeserv", "(Service) ValeDark" = "valeservdark", + "(Janitor) Scrubpuppy" = "scrubpup") + for(var/a in L) + var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a]) + wide.pixel_x = -16 + service_icons[a] = wide + if(R.client && R.client.ckey == "nezuli") + var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-sec") + bad_snowflake.pixel_x = -16 + service_icons["Alina"] = bad_snowflake + service_icons = sortList(service_icons) + var/service_robot_icon = show_radial_menu(R, R , service_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE) + switch(service_robot_icon) if("(Service) Waitress") cyborg_base_icon = "service_f" special_light_key = "service" @@ -799,6 +897,8 @@ cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi' sleeper_overlay = "jsleeper" dogborg = TRUE + else + return FALSE return ..() /obj/item/robot_module/miner @@ -833,10 +933,25 @@ /obj/item/robot_module/miner/be_transformed_to(obj/item/robot_module/old_module) var/mob/living/silicon/robot/R = loc - var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Lavaland", "Heavy", "Sleek", "Marina", "Can", "Spider", "Asteroid", "Droid", "Blade", "Vale") - if(!borg_icon) - return FALSE - switch(borg_icon) + var/static/list/mining_icons + if(!mining_icons) + mining_icons = list( + "Lavaland" = image(icon = 'icons/mob/robots.dmi', icon_state = "miner"), + "Asteroid" = image(icon = 'icons/mob/robots.dmi', icon_state = "minerOLD"), + "Droid" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "miner"), + "Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekmin"), + "Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinamin"), + "Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "canmin"), + "Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymin"), + ) + var/list/L = list("Blade" = "blade", "Vale" = "valemine") + for(var/a in L) + var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a]) + wide.pixel_x = -16 + mining_icons[a] = wide + mining_icons = sortList(mining_icons) + var/mining_borg_icon = show_radial_menu(R, R , mining_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE) + switch(mining_borg_icon) if("Lavaland") cyborg_base_icon = "miner" if("Asteroid") @@ -871,6 +986,8 @@ cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi' sleeper_overlay = "valeminesleeper" dogborg = TRUE + else + return FALSE return ..() /obj/item/robot_module/syndicate diff --git a/code/modules/mob/living/silicon/robot/update_icons.dm b/code/modules/mob/living/silicon/robot/update_icons.dm index 72ad21c51e..a567446e9e 100644 --- a/code/modules/mob/living/silicon/robot/update_icons.dm +++ b/code/modules/mob/living/silicon/robot/update_icons.dm @@ -57,3 +57,5 @@ cut_overlays() else icon_state = "[module.cyborg_base_icon]" + + SEND_SIGNAL(src, COMSIG_ROBOT_UPDATE_ICONS) diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm index d03785f71c..f3cedf43cf 100644 --- a/code/modules/mob/living/silicon/silicon_defense.dm +++ b/code/modules/mob/living/silicon/silicon_defense.dm @@ -17,7 +17,8 @@ log_combat(M, src, "attacked") playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) visible_message("[M] has slashed at [src]!", \ - "[M] has slashed at [src]!") + "[M] has slashed at you!", target = M, \ + target_message = "You have slashed at [src]!") if(prob(8)) flash_act(affect_silicon = 1) log_combat(M, src, "attacked") @@ -25,8 +26,9 @@ updatehealth() else playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - visible_message("[M] took a swipe at [src]!", \ - "[M] took a swipe at [src]!") + visible_message("[M] take a swipe at [src]!", \ + "[M] take a swipe at you!", target = M, \ + target_message = "You take a swipe at [src]!") /mob/living/silicon/attack_animal(mob/living/simple_animal/M) . = ..() @@ -36,7 +38,8 @@ for(var/mob/living/N in buckled_mobs) N.DefaultCombatKnockdown(20) unbuckle_mob(N) - N.visible_message("[N] is knocked off of [src] by [M]!") + N.visible_message("[N] is knocked off of [src] by [M]!", + "You are knocked off of [src] by [M]!") switch(M.melee_damage_type) if(BRUTE) adjustBruteLoss(damage) @@ -62,7 +65,8 @@ adjustBruteLoss(rand(10, 15)) playsound(loc, "punch", 25, 1, -1) visible_message("[user] has punched [src]!", \ - "[user] has punched [src]!") + "[user] has punched you!", target = user, \ + target_message = "You have punched [src]!") return TRUE return FALSE @@ -73,14 +77,16 @@ switch(M.a_intent) if (INTENT_HELP) M.visible_message("[M] pets [src].", \ - "You pet [src].") + "You pet [src].", target = src, + target_message = "[M] pets you.") if(INTENT_GRAB) grabbedby(M) else M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) playsound(src.loc, 'sound/effects/bang.ogg', 10, 1) visible_message("[M] punches [src], but doesn't leave a dent.", \ - "[M] punches [src], but doesn't leave a dent.", null, COMBAT_MESSAGE_RANGE) + "[M] punches you, but doesn't leave a dent.", null, COMBAT_MESSAGE_RANGE, null, M, + "You punch [src], but don't leave a dent.") /mob/living/silicon/attack_drone(mob/living/simple_animal/drone/M) if(M.a_intent == INTENT_HARM) @@ -109,14 +115,15 @@ if(prob(severity*50)) unbuckle_mob(M) M.DefaultCombatKnockdown(40) - M.visible_message("[M] is thrown off of [src]!") + M.visible_message("[M] is thrown off of [src]!", + "You are thrown off of [src]!") flash_act(affect_silicon = 1) /mob/living/silicon/bullet_act(obj/item/projectile/P, def_zone) var/totaldamage = P.damage if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself var/list/returnlist = list() - var/returned = run_block(P, P.damage, "the [P.name]", ATTACK_TYPE_PROJECTILE, P.armour_penetration, P.firer, def_zone, returnlist) + var/returned = mob_run_block(P, P.damage, "the [P.name]", ATTACK_TYPE_PROJECTILE, P.armour_penetration, P.firer, def_zone, returnlist) if(returned & BLOCK_SHOULD_REDIRECT) handle_projectile_attack_redirection(P, returnlist[BLOCK_RETURN_REDIRECT_METHOD]) if(returned & BLOCK_REDIRECTED) @@ -129,7 +136,8 @@ adjustBruteLoss(totaldamage) if((P.damage >= 10) || P.stun || P.knockdown || (P.stamina >= 20)) for(var/mob/living/M in buckled_mobs) - M.visible_message("[M] is knocked off of [src]!") + M.visible_message("[M] is knocked off of [src] by the [P]!", + "You are knocked off of [src] by the [P]!") unbuckle_mob(M) M.DefaultCombatKnockdown(40) P.on_hit(src) diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm index fe18d48718..1e56e91ae1 100644 --- a/code/modules/mob/living/simple_animal/animal_defense.dm +++ b/code/modules/mob/living/simple_animal/animal_defense.dm @@ -7,7 +7,9 @@ switch(M.a_intent) if(INTENT_HELP) if (health > 0) - visible_message("[M] [response_help] [src].") + visible_message("[M] [response_help_continuous] [src].", \ + "[M] [response_help_continuous] you.", null, null, null, + M, "You [response_help_simple] [src].") playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) if(INTENT_GRAB) @@ -16,13 +18,22 @@ else grabbedby(M) - if(INTENT_HARM, INTENT_DISARM) + if(INTENT_DISARM) + M.do_attack_animation(src, ATTACK_EFFECT_DISARM) + visible_message("[M] [response_disarm_continuous] [src]!",\ + "[M] [response_disarm_continuous] you!", null, COMBAT_MESSAGE_RANGE, null, \ + M, "You [response_disarm_simple] [src]!") + playsound(src, 'sound/weapons/thudswoosh.ogg', 25, 1) + log_combat(M, src, "disarmed") + + if(INTENT_HARM) if(HAS_TRAIT(M, TRAIT_PACIFISM)) to_chat(M, "You don't want to hurt [src]!") return M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) - visible_message("[M] [response_harm] [src]!",\ - "[M] [response_harm] [src]!", null, COMBAT_MESSAGE_RANGE) + visible_message("[M] [response_harm_continuous] [src]!",\ + "[M] [response_harm_continuous] you!", null, COMBAT_MESSAGE_RANGE, null, \ + M, "You [response_harm_simple] [src]!") playsound(loc, attacked_sound, 25, 1, -1) attack_threshold_check(harm_intent_damage) log_combat(M, src, "attacked") @@ -35,8 +46,9 @@ if(.) return playsound(loc, "punch", 25, 1, -1) - visible_message("[user] has punched [src]!", \ - "[user] has punched [src]!", null, COMBAT_MESSAGE_RANGE) + visible_message("[user] punches [src]!", \ + "[user] punches you!", null, COMBAT_MESSAGE_RANGE, null, \ + user, "You punch [src]!") adjustBruteLoss(15) return TRUE @@ -48,7 +60,9 @@ return 1 if (M.a_intent == INTENT_HELP) if (health > 0) - visible_message("[M.name] [response_help] [src].") + visible_message("[M.name] [response_help_continuous] [src].", \ + "[M.name] [response_help_continuous] you.", \ + target = M, target_message = "You [response_help_simple] [src].") playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) /mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M) @@ -57,12 +71,14 @@ return if(M.a_intent == INTENT_DISARM) playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) - visible_message("[M] [response_disarm] [name]!", \ - "[M] [response_disarm] [name]!", null, COMBAT_MESSAGE_RANGE) + visible_message("[M] [response_disarm_continuous] [name]!", \ + "[M] [response_disarm_continuous] [name]!", null, COMBAT_MESSAGE_RANGE, null, \ + M, "You [response_disarm_simple] [name]!") log_combat(M, src, "disarmed") else visible_message("[M] has slashed at [src]!", \ - "[M] has slashed at [src]!", null, COMBAT_MESSAGE_RANGE) + "[M] has slashed at [src]!", null, COMBAT_MESSAGE_RANGE, null, \ + M, "[M] has slashed at [src]!") playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) attack_threshold_check(M.meleeSlashSAPower) log_combat(M, src, "attacked") @@ -102,7 +118,7 @@ temp_damage *= damage_coeff[damagetype] if(temp_damage >= 0 && temp_damage <= force_threshold) - visible_message("[src] looks unharmed.") + visible_message("[src] looks unharmed!") return FALSE else apply_damage(damage, damagetype, null, getarmor(null, armorcheck)) diff --git a/code/modules/mob/living/simple_animal/astral.dm b/code/modules/mob/living/simple_animal/astral.dm index ebc89e2577..4fb9e9273e 100644 --- a/code/modules/mob/living/simple_animal/astral.dm +++ b/code/modules/mob/living/simple_animal/astral.dm @@ -5,10 +5,15 @@ icon_state = "ghost" icon_living = "ghost" mob_biotypes = MOB_SPIRIT - attacktext = "raises the hairs on the neck of" - response_harm = "disrupts the concentration of" - response_disarm = "wafts" - friendly = "communes with" + has_field_of_vision = FALSE //we are a spoopy ghost + attack_verb_continuous = "raises the hair on the neck of" + attack_verb_simple = "raise the hair on the neck of" + response_harm_continuous = "disrupts the concentration of" + response_harm_simple = "disrupt the concentration of" + response_disarm_continuous = "wafts" + response_disarm_simple = "waft" + friendly_verb_continuous = "communes with" + friendly_verb_simple = "commute with" loot = null maxHealth = 10 health = 10 @@ -18,7 +23,6 @@ deathmessage = "disappears as if it was never really there to begin with" incorporeal_move = 1 alpha = 50 - attacktext = "touches the mind of" speak_emote = list("echos") movement_type = FLYING var/pseudo_death = FALSE @@ -32,7 +36,6 @@ /mob/living/simple_animal/astral/death() icon_state = "shade_dead" Stun(1000) - friendly = "deads at" pseudo_death = TRUE incorporeal_move = 0 to_chat(src, "Your astral projection is interrupted and your mind is sent back to your body with a shock!") @@ -49,14 +52,14 @@ to_chat(src, "The intensity of the astrogen in your body is too much allow you to return to yourself yet!") return to_chat(src, "You astrally possess [H]!") - log_game("FERMICHEM: [src] has astrally possessed [A]!") + log_reagent("FERMICHEM: [src] has astrally possessed [A]!") src.mind.transfer_to(H) qdel(src) var/message = html_decode(stripped_input(src, "Enter a message to send to [A]", MAX_MESSAGE_LEN)) if(!message) return to_chat(A, "[src] projects into your mind, \"[message]\"") - log_game("FERMICHEM: [src] has astrally transmitted [message] into [A]") + log_reagent("FERMICHEM: [src] has astrally transmitted [message] into [A]") //Delete the mob if there's no mind! Pay that mob no mind. /mob/living/simple_animal/astral/Life() diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index a8e0d2c1c8..97f3dad3f0 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -911,7 +911,6 @@ Pass a positive integer as an argument to override a bot's default speed. bot_name = name name = paicard.pai.name faction = user.faction.Copy() - language_holder = paicard.pai.language_holder.copy(src) log_combat(user, paicard.pai, "uploaded to [bot_name],") return TRUE else diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm index adb49938e1..73099d8d9f 100644 --- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm +++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm @@ -20,9 +20,7 @@ weather_immunities = list("lava","ash") var/clean_time = 50 //How long do we take to clean? - var/broom = FALSE //Do we have an speed buff from a broom? - var/adv_mop = FALSE //Do we have a cleaning buff from a better mop? - + var/upgrades = 0 var/blood = 1 var/trash = 0 @@ -79,26 +77,38 @@ if(open) to_chat(user, "Please close the access panel before locking it.") else - to_chat(user, "\The [src] doesn't seem to respect your authority.") + to_chat(user, "The [src] doesn't seem to respect your authority.") - if(istype(W, /obj/item/mop/advanced)) - if(bot_core.allowed(user) && open && adv_mop == TRUE) + else if(istype(W, /obj/item/mop/advanced)) + if(bot_core.allowed(user) && open && !CHECK_BITFIELD(upgrades,UPGRADE_CLEANER_ADVANCED_MOP)) to_chat(user, "You replace \the [src] old mop with a new better one!") - adv_mop = TRUE + upgrades |= UPGRADE_CLEANER_ADVANCED_MOP clean_time = 20 //2.5 the speed! window_name = "Automatic Station Cleaner v2.1 BETA" //New! qdel(W) + if(!open) + to_chat(user, "The [src] access pannle is not open!") + return + if(!bot_core.allowed(user)) + to_chat(user, "The [src] access pannel locked off to you!") + return else - to_chat(user, "\the [src] already has this mop!") + to_chat(user, "The [src] already has this mop!") - if(istype(W, /obj/item/twohanded/broom)) - if(bot_core.allowed(user) && open && broom == TRUE) + else if(istype(W, /obj/item/twohanded/broom)) + if(bot_core.allowed(user) && open && !CHECK_BITFIELD(upgrades,UPGRADE_CLEANER_BROOM)) to_chat(user, "You add to \the [src] a broom speeding it up!") - broom = TRUE + upgrades |= UPGRADE_CLEANER_BROOM base_speed = 1 //2x faster! qdel(W) + if(!open) + to_chat(user, "The [src] access pannel is not open!") + return + if(!bot_core.allowed(user)) + to_chat(user, "The [src] access pannel locked off to you!") + return else - to_chat(user, "\the [src] already has a broom!") + to_chat(user, "The [src] already has a broom!") else return ..() diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm index 6c4680a477..08fffc2cf8 100644 --- a/code/modules/mob/living/simple_animal/bot/construction.dm +++ b/code/modules/mob/living/simple_animal/bot/construction.dm @@ -147,9 +147,8 @@ to_chat(user, "You need one length of cable to wire the ED-209!") return to_chat(user, "You start to wire [src]...") - if(do_after(user, 40, target = src)) - if(coil.get_amount() >= 1 && build_step == 6) - coil.use(1) + if(coil.use_tool(src, user, 40, 1)) + if(build_step == 6) to_chat(user, "You wire [src].") name = "wired ED-209 assembly" build_step++ diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index 469a395169..6febb942a1 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -44,8 +44,6 @@ var/cell_type = /obj/item/stock_parts/cell var/vest_type = /obj/item/clothing/suit/armor/vest - do_footstep = TRUE - /mob/living/simple_animal/bot/ed209/Initialize(mapload,created_name,created_lasercolor) . = ..() diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm index 1bf3883ea7..0f4608f48c 100644 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm @@ -33,6 +33,8 @@ var/oldloc = null var/toolbox = /obj/item/storage/toolbox/mechanical + var/upgrades = 0 + #define HULL_BREACH 1 #define LINE_SPACE_MODE 2 #define FIX_TILE 3 @@ -120,6 +122,36 @@ to_chat(user, "You load [loaded] tiles into the floorbot. It now contains [specialtiles] tiles.") else to_chat(user, "You need at least one floor tile to put into [src]!") + + else if(istype(W, /obj/item/storage/toolbox/artistic)) + if(bot_core.allowed(user) && open && !CHECK_BITFIELD(upgrades,UPGRADE_FLOOR_ARTBOX)) + to_chat(user, "You upgrade \the [src] case to hold more!") + upgrades |= UPGRADE_FLOOR_ARTBOX + maxtiles += 100 //Double the storage! + qdel(W) + if(!open) + to_chat(user, "The [src] access pannle is not open!") + return + if(!bot_core.allowed(user)) + to_chat(user, "The [src] access pannel locked off to you!") + return + else + to_chat(user, "The [src] already has a upgraded case!") + + else if(istype(W, /obj/item/storage/toolbox/syndicate)) + if(bot_core.allowed(user) && open && !CHECK_BITFIELD(upgrades,UPGRADE_FLOOR_SYNDIBOX)) + to_chat(user, "You upgrade \the [src] case to hold more!") + upgrades |= UPGRADE_FLOOR_SYNDIBOX + maxtiles += 200 //Double bse storage + base_speed = 1 //2x faster! + qdel(W) + if(!bot_core.allowed(user)) + to_chat(user, "The [src] access pannel locked off to you!") + return + else + to_chat(user, "The [src] already has a upgraded case!") + + else ..() diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index e4e81bb5db..7d93669c31 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -42,6 +42,7 @@ var/declare_crit = 1 //If active, the bot will transmit a critical patient alert to MedHUD users. var/declare_cooldown = 0 //Prevents spam of critical patient alerts. var/stationary_mode = 0 //If enabled, the Medibot will not move automatically. + var/injection_time = 30 //How long we take to inject someone //Setting which reagents to use to treat what by default. By id. var/treatment_brute_avoid = /datum/reagent/medicine/tricordrazine var/treatment_brute = /datum/reagent/medicine/bicaridine @@ -51,19 +52,25 @@ var/treatment_fire = /datum/reagent/medicine/kelotane var/treatment_tox_avoid = /datum/reagent/medicine/tricordrazine var/treatment_tox = /datum/reagent/medicine/charcoal - var/treatment_tox_toxlover = /datum/reagent/toxin + var/treatment_tox_toxlover = /datum/reagent/toxin //Injects toxins into people that heal via toxins var/treatment_virus_avoid = null var/treatment_virus = /datum/reagent/medicine/spaceacillin var/treat_virus = 1 //If on, the bot will attempt to treat viral infections, curing them if possible. var/shut_up = 0 //self explanatory :) + var/upgrades = 0 + var/upgraded_dispenser_1 //Do we have the nicer chemicals? - replaces dex with salbutamol + var/upgraded_dispenser_2 //Do we have the nicer chemicals? - replaces kep with oxandrolone + var/upgraded_dispenser_3 //Do we have the nicer chemicals? - replaces bic with sal acid + var/upgraded_dispenser_4 //Do we have the nicer chemicals? - replaces charcoal/toxin with pentetic acid / pentetic jelly + /mob/living/simple_animal/bot/medbot/mysterious name = "\improper Mysterious Medibot" desc = "International Medibot of mystery." skin = "bezerk" - treatment_brute = /datum/reagent/medicine/tricordrazine - treatment_fire = /datum/reagent/medicine/tricordrazine - treatment_tox = /datum/reagent/medicine/tricordrazine + treatment_brute = /datum/reagent/medicine/regen_jelly + treatment_fire = /datum/reagent/medicine/regen_jelly + treatment_tox = /datum/reagent/medicine/regen_jelly /mob/living/simple_animal/bot/medbot/derelict name = "\improper Old Medibot" @@ -220,7 +227,6 @@ /mob/living/simple_animal/bot/medbot/attackby(obj/item/W as obj, mob/user as mob, params) if(istype(W, /obj/item/reagent_containers/glass)) - . = 1 //no afterattack if(locked) to_chat(user, "You cannot insert a beaker because the panel is locked!") return @@ -234,6 +240,97 @@ to_chat(user, "You insert [W].") show_controls(user) + else if(istype(W, /obj/item/reagent_containers/syringe/piercing)) + if(bot_core.allowed(user) && open && !CHECK_BITFIELD(upgrades,UPGRADE_MEDICAL_PIERERCING)) + to_chat(user, "You replace \the [src] syringe with a diamond-tipped one!") + upgrades |= UPGRADE_MEDICAL_PIERERCING + qdel(W) + if(!open) + to_chat(user, "The [src] access pannel is not open!") + return + if(!bot_core.allowed(user)) + to_chat(user, "The [src] access pannel locked off to you!") + return + else + to_chat(user, "The [src] already has a diamond-tipped syringe!") + + else if(istype(W, /obj/item/hypospray/mkii)) + if(bot_core.allowed(user) && open && !CHECK_BITFIELD(upgrades,UPGRADE_MEDICAL_HYPOSPRAY)) + to_chat(user, "You replace \the [src] syringe base with a DeForest Medical MK.II Hypospray!") + upgrades |= UPGRADE_MEDICAL_HYPOSPRAY + injection_time = 15 //Half the time half the death! + window_name = "Automatic Medical Unit v2.4 ALPHA" + qdel(W) + if(!open) + to_chat(user, "The [src] access pannel is not open!") + return + if(!bot_core.allowed(user)) + to_chat(user, "The [src] access pannel locked off to you!") + return + else + to_chat(user, "The [src] already has a DeForest Medical Hypospray base!") + + else if(istype(W, /obj/item/circuitboard/machine/chem_dispenser)) + if(bot_core.allowed(user) && open && !CHECK_BITFIELD(upgrades,UPGRADE_MEDICAL_CHEM_BOARD)) + to_chat(user, "You add in the board upgrading \the [src] reagent banks!") + upgrades |= UPGRADE_MEDICAL_CHEM_BOARD + treatment_oxy = /datum/reagent/medicine/salbutamol //Replaces Dex with salbutamol "better" healing of o2 + qdel(W) + if(!open) + to_chat(user, "The [src] access pannel is not open!") + return + if(!bot_core.allowed(user)) + to_chat(user, "The [src] access pannel locked off to you!") + return + else + to_chat(user, "The [src] already has this upgrade!") + + else if(istype(W, /obj/item/circuitboard/machine/cryo_tube)) + if(bot_core.allowed(user) && open && !CHECK_BITFIELD(upgrades,UPGRADE_MEDICAL_CRYO_BOARD)) + to_chat(user, "You add in the board upgrading \the [src] reagent banks!") + upgrades |= UPGRADE_MEDICAL_CRYO_BOARD + treatment_fire = /datum/reagent/medicine/oxandrolone //Replaces Kep with oxandrolone "better" healing of burns + qdel(W) + if(!open) + to_chat(user, "The [src] access pannel is not open!") + return + if(!bot_core.allowed(user)) + to_chat(user, "The [src] access pannel locked off to you!") + return + else + to_chat(user, "The [src] already has this upgrade!") + + else if(istype(W, /obj/item/circuitboard/machine/chem_master)) + if(bot_core.allowed(user) && open && !CHECK_BITFIELD(upgrades,UPGRADE_MEDICAL_CHEM_MASTER)) + to_chat(user, "You add in the board upgrading \the [src] reagent banks!") + upgrades |= UPGRADE_MEDICAL_CHEM_MASTER + treatment_brute = /datum/reagent/medicine/sal_acid //Replaces Bic with Sal Acid "better" healing of brute + qdel(W) + if(!open) + to_chat(user, "the [src] access pannel is not open!") + return + if(!bot_core.allowed(user)) + to_chat(user, "the [src] access pannel locked off to you!") + return + else + to_chat(user, "the [src] already has this upgrade!") + + else if(istype(W, /obj/item/circuitboard/machine/sleeper)) + if(bot_core.allowed(user) && open && !CHECK_BITFIELD(upgrades,UPGRADE_MEDICAL_SLEEP_BOARD)) + to_chat(user, "You add in the board upgrading \the [src] reagent banks!") + upgrades |= UPGRADE_MEDICAL_SLEEP_BOARD + treatment_tox = /datum/reagent/medicine/pen_acid //replaces charcoal with pen acid a "better" healing of toxins + treatment_tox_toxlover = /datum/reagent/medicine/pen_acid/pen_jelly //Injects pen jelly into people that heal via toxins + qdel(W) + if(!open) + to_chat(user, "The [src] access pannle is not open!") + return + if(!bot_core.allowed(user)) + to_chat(user, "The [src] access pannel locked off to you!") + return + else + to_chat(user, "The [src] already has this upgrade!") + else var/current_health = health ..() @@ -249,6 +346,8 @@ audible_message("[src] buzzes oddly!") flick("medibot_spark", src) playsound(src, "sparks", 75, 1) + if(!CHECK_BITFIELD(upgrades,UPGRADE_MEDICAL_PIERERCING)) + upgrades |= UPGRADE_MEDICAL_PIERERCING //Jabs even harder through the clothing! if(user) oldpatient = user @@ -361,7 +460,7 @@ if(ishuman(C)) var/mob/living/carbon/human/H = C - if (H.wear_suit && H.head && istype(H.wear_suit, /obj/item/clothing) && istype(H.head, /obj/item/clothing)) + if (H.wear_suit && H.head && istype(H.wear_suit, /obj/item/clothing) && istype(H.head, /obj/item/clothing) && !CHECK_BITFIELD(upgrades,UPGRADE_MEDICAL_PIERERCING)) var/obj/item/clothing/CS = H.wear_suit var/obj/item/clothing/CH = H.head if (CS.clothing_flags & CH.clothing_flags & THICKMATERIAL) @@ -418,7 +517,7 @@ else ..() -/mob/living/simple_animal/bot/medbot/examinate(atom/A as mob|obj|turf in view()) +/mob/living/simple_animal/bot/medbot/examinate(atom/A as mob|obj|turf in fov_view()) ..() if(!is_blind(src)) chemscan(src, A) @@ -504,7 +603,7 @@ "[src] is trying to inject you!") var/failed = FALSE - if(do_mob(src, patient, 30)) //Is C == patient? This is so confusing + if(do_mob(src, patient, injection_time)) //Is C == patient? This is so confusing if((get_dist(src, patient) <= 1) && (on) && assess_patient(patient)) if(reagent_id == "internal_beaker") if(use_beaker && reagent_glass && reagent_glass.reagents.total_volume) diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 674cc722d8..354bc9ed0f 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -5,9 +5,12 @@ gender = NEUTER mob_biotypes = NONE speak_emote = list("hisses") - response_help = "thinks better of touching" - response_disarm = "flails at" - response_harm = "punches" + response_help_continuous = "thinks better of touching" + response_help_simple = "think better of touching" + response_disarm_continuous = "flails at" + response_disarm_simple = "flail at" + response_harm_continuous = "punches" + response_harm_simple = "punch" threat = 1 speak_chance = 1 icon = 'icons/mob/mob.dmi' @@ -122,12 +125,14 @@ threat = 3 maxHealth = 150 health = 150 - response_harm = "harmlessly punches" + response_harm_continuous = "harmlessly punches" + response_harm_simple = "harmlessly punch" harm_intent_damage = 0 obj_damage = 90 melee_damage_lower = 25 melee_damage_upper = 25 - attacktext = "smashes their armored gauntlet into" + attack_verb_continuous = "smashes their armored gauntlet into" + attack_verb_simple = "smash your armored gauntlet into" speed = 2.5 environment_smash = ENVIRONMENT_SMASH_WALLS attack_sound = 'sound/weapons/punch3.ogg' @@ -188,7 +193,8 @@ melee_damage_lower = 20 melee_damage_upper = 20 retreat_distance = 2 //AI wraiths will move in and out of combat - attacktext = "slashes" + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" attack_sound = 'sound/weapons/bladeslice.ogg' construct_spells = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift) runetype = /datum/action/innate/cult/create_rune/tele @@ -232,14 +238,16 @@ icon_living = "artificer" maxHealth = 50 health = 50 - response_harm = "viciously beats" + response_harm_continuous = "viciously beats" + response_harm_simple = "viciously beat" harm_intent_damage = 5 obj_damage = 60 melee_damage_lower = 5 melee_damage_upper = 5 retreat_distance = 10 minimum_distance = 10 //AI artificers will flee like fuck - attacktext = "rams" + attack_verb_continuous = "rams" + attack_verb_simple = "ram" environment_smash = ENVIRONMENT_SMASH_WALLS attack_sound = 'sound/weapons/punch2.ogg' construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/wall, @@ -319,7 +327,8 @@ sight = SEE_MOBS melee_damage_lower = 15 melee_damage_upper = 20 - attacktext = "butchers" + attack_verb_continuous = "butchers" + attack_verb_simple = "butcher" attack_sound = 'sound/weapons/bladeslice.ogg' construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/area_conversion, /obj/effect/proc_holder/spell/targeted/forcewall/cult) diff --git a/code/modules/mob/living/simple_animal/friendly/bumbles.dm b/code/modules/mob/living/simple_animal/friendly/bumbles.dm index 1a78a47031..2d236a4327 100644 --- a/code/modules/mob/living/simple_animal/friendly/bumbles.dm +++ b/code/modules/mob/living/simple_animal/friendly/bumbles.dm @@ -5,14 +5,18 @@ icon_living = "bumbles" icon_dead = "bumbles_dead" turns_per_move = 1 - response_help = "pets" - response_disarm = "brushes aside" - response_harm = "squashes" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "brushes aside" + response_help_simple = "brush aside" + response_harm_continuous = "squashes" + response_harm_simple = "squash" speak_emote = list("buzzes") maxHealth = 100 health = 100 harm_intent_damage = 1 - friendly = "bzzs" + friendly_verb_continuous = "bzzs" + friendly_verb_simple = "bzz" density = FALSE movement_type = FLYING pass_flags = PASSTABLE | PASSGRILLE | PASSMOB diff --git a/code/modules/mob/living/simple_animal/friendly/butterfly.dm b/code/modules/mob/living/simple_animal/friendly/butterfly.dm index 80fba5a9a4..bf4f45e283 100644 --- a/code/modules/mob/living/simple_animal/friendly/butterfly.dm +++ b/code/modules/mob/living/simple_animal/friendly/butterfly.dm @@ -5,14 +5,18 @@ icon_living = "butterfly" icon_dead = "butterfly_dead" turns_per_move = 1 - response_help = "shoos" - response_disarm = "brushes aside" - response_harm = "squashes" + response_help_continuous = "shoos" + response_help_simple = "shoo" + response_disarm_continuous = "brushes aside" + response_disarm_simple = "brush aside" + response_harm_continuous = "squashes" + response_harm_simple = "squash" speak_emote = list("flutters") maxHealth = 2 health = 2 harm_intent_damage = 1 - friendly = "nudges" + friendly_verb_continuous = "nudges" + friendly_verb_simple = "nudge" density = FALSE movement_type = FLYING pass_flags = PASSTABLE | PASSGRILLE | PASSMOB diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index 1297fddb69..5f7ff198e2 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -24,15 +24,18 @@ animal_species = /mob/living/simple_animal/pet/cat childtype = list(/mob/living/simple_animal/pet/cat/kitten) butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2, /obj/item/organ/ears/cat = 1, /obj/item/organ/tail/cat = 1) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" var/turns_since_scan = 0 var/mob/living/simple_animal/mouse/movement_target gold_core_spawnable = FRIENDLY_SPAWN collar_type = "cat" var/held_icon = "cat2" - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_CLAW /mob/living/simple_animal/pet/cat/Initialize() . = ..() @@ -87,7 +90,6 @@ pass_flags = PASSMOB mob_size = MOB_SIZE_SMALL collar_type = "kitten" - held_icon = "cat" //RUNTIME IS ALIVE! SQUEEEEEEEE~ /mob/living/simple_animal/pet/cat/Runtime @@ -99,6 +101,7 @@ gender = FEMALE gold_core_spawnable = NO_SPAWN unique_pet = TRUE + held_icon = "cat" var/list/family = list()//var restored from savefile, has count of each child type var/list/children = list()//Actual mob instances of children var/cats_deployed = 0 @@ -245,7 +248,8 @@ harm_intent_damage = 10 butcher_results = list(/obj/item/organ/brain = 1, /obj/item/organ/heart = 1, /obj/item/reagent_containers/food/snacks/cakeslice/birthday = 3, \ /obj/item/reagent_containers/food/snacks/meat/slab = 2) - response_harm = "takes a bite out of" + response_harm_continuous = "takes a bite out of" + response_harm_simple = "take a bite out of" attacked_sound = 'sound/items/eatfood.ogg' deathmessage = "loses its false life and collapses!" death_sound = "bodyfall" @@ -306,7 +310,6 @@ if (pseudo_death == TRUE) //secret cat chem icon_state = "custom_cat_dead" Stun(1000) - friendly = "deads at" return else ..() diff --git a/code/modules/mob/living/simple_animal/friendly/cockroach.dm b/code/modules/mob/living/simple_animal/friendly/cockroach.dm index 95aa86aaab..9a34f2c176 100644 --- a/code/modules/mob/living/simple_animal/friendly/cockroach.dm +++ b/code/modules/mob/living/simple_animal/friendly/cockroach.dm @@ -14,9 +14,12 @@ pass_flags = PASSTABLE | PASSGRILLE | PASSMOB mob_size = MOB_SIZE_TINY mob_biotypes = MOB_ORGANIC|MOB_BUG - response_help = "pokes" - response_disarm = "shoos" - response_harm = "splats" + response_help_continuous = "pokes" + response_help_simple = "poke" + response_disarm_continuous = "shoos" + response_disarm_simple = "shoo" + response_harm_continuous = "splats" + response_harm_simple = "splat" speak_emote = list("chitters") density = FALSE ventcrawler = VENTCRAWLER_ALWAYS diff --git a/code/modules/mob/living/simple_animal/friendly/crab.dm b/code/modules/mob/living/simple_animal/friendly/crab.dm index cce5edc513..d86362c974 100644 --- a/code/modules/mob/living/simple_animal/friendly/crab.dm +++ b/code/modules/mob/living/simple_animal/friendly/crab.dm @@ -12,11 +12,15 @@ speak_chance = 1 turns_per_move = 5 butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/rawcrab = 4) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "stomps" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "stomps" + response_harm_continuous = "stomp" stop_automated_movement = 1 - friendly = "pinches" + friendly_verb_continuous = "pinches" + friendly_verb_simple = "pinch" ventcrawler = VENTCRAWLER_ALWAYS var/obj/item/inventory_head var/obj/item/inventory_mask @@ -41,9 +45,6 @@ real_name = "Coffee" desc = "It's Coffee, the other pet!" gender = FEMALE - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "stomps" gold_core_spawnable = NO_SPAWN /mob/living/simple_animal/crab/evil @@ -53,9 +54,10 @@ icon_state = "evilcrab" icon_living = "evilcrab" icon_dead = "evilcrab_dead" - response_help = "pokes" - response_disarm = "shoves" - response_harm = "stomps" + response_help_continuous = "pokes" + response_help_simple = "poke" + response_disarm_continuous = "shoves" + response_disarm_simple = "shove" gold_core_spawnable = HOSTILE_SPAWN /mob/living/simple_animal/crab/kreb @@ -65,9 +67,6 @@ icon_state = "kreb" icon_living = "kreb" icon_dead = "kreb_dead" - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "stomps" gold_core_spawnable = NO_SPAWN /mob/living/simple_animal/crab/evil/kreb diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm index 485cece8b7..57a4ecc5c9 100644 --- a/code/modules/mob/living/simple_animal/friendly/dog.dm +++ b/code/modules/mob/living/simple_animal/friendly/dog.dm @@ -2,9 +2,12 @@ /mob/living/simple_animal/pet/dog mob_biotypes = MOB_ORGANIC|MOB_BEAST - response_help = "pets" - response_disarm = "bops" - response_harm = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "bops" + response_disarm_simple = "bop" + response_harm_continuous = "kicks" + response_harm_simple = "kick" speak = list("YAP", "Woof!", "Bark!", "AUUUUUU") speak_emote = list("barks", "woofs") emote_hear = list("barks!", "woofs!", "yaps.","pants.") @@ -15,7 +18,7 @@ turns_per_move = 10 var/held_icon = "corgi" - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_CLAW /mob/living/simple_animal/pet/dog/ComponentInitialize() . = ..() @@ -332,9 +335,6 @@ desc = "It's the HoP's beloved corgi." var/turns_since_scan = 0 var/obj/movement_target - response_help = "pets" - response_disarm = "bops" - response_harm = "kicks" gold_core_spawnable = NO_SPAWN unique_pet = TRUE var/age = 0 @@ -604,9 +604,6 @@ icon_state = "lisa" icon_living = "lisa" icon_dead = "lisa_dead" - response_help = "pets" - response_disarm = "bops" - response_harm = "kicks" var/turns_since_scan = 0 var/puppies = 0 held_icon = "lisa" diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index e67e649ac6..e9bc3c549d 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -13,13 +13,17 @@ turns_per_move = 5 see_in_dark = 6 butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 4) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" faction = list("neutral") mob_biotypes = MOB_ORGANIC|MOB_BEAST attack_same = 1 - attacktext = "kicks" + attack_verb_continuous = "kicks" + attack_verb_simple = "kick" attack_sound = 'sound/weapons/punch1.ogg' health = 40 maxHealth = 40 @@ -30,7 +34,7 @@ blood_volume = BLOOD_VOLUME_NORMAL var/obj/item/udder/udder = null - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_SHOE /mob/living/simple_animal/hostile/retaliate/goat/Initialize() udder = new() @@ -121,10 +125,14 @@ turns_per_move = 5 see_in_dark = 6 butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 6) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" - attacktext = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" + attack_verb_continuous = "kicks" + attack_verb_simple = "kick" attack_sound = 'sound/weapons/punch1.ogg' health = 50 maxHealth = 50 @@ -132,7 +140,7 @@ gold_core_spawnable = FRIENDLY_SPAWN blood_volume = BLOOD_VOLUME_NORMAL - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_SHOE /mob/living/simple_animal/cow/Initialize() udder = new() @@ -198,10 +206,14 @@ speak_chance = 2 turns_per_move = 2 butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/chicken = 1) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" - attacktext = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" + attack_verb_continuous = "kicks" + attack_verb_simple = "kick" health = 3 maxHealth = 3 ventcrawler = VENTCRAWLER_ALWAYS @@ -210,7 +222,7 @@ mob_size = MOB_SIZE_TINY gold_core_spawnable = FRIENDLY_SPAWN - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_CLAW /mob/living/simple_animal/chick/Initialize() . = ..() @@ -249,10 +261,14 @@ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/chicken = 2) var/egg_type = /obj/item/reagent_containers/food/snacks/egg var/food_type = /obj/item/reagent_containers/food/snacks/grown/wheat - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" - attacktext = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" + attack_verb_continuous = "kicks" + attack_verb_simple = "kick" health = 15 maxHealth = 15 ventcrawler = VENTCRAWLER_ALWAYS @@ -268,7 +284,7 @@ gold_core_spawnable = FRIENDLY_SPAWN var/static/chicken_count = 0 - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_CLAW /mob/living/simple_animal/chicken/Initialize() . = ..() @@ -342,10 +358,14 @@ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 3) var/egg_type = /obj/item/reagent_containers/food/snacks/egg/kiwiEgg var/food_type = /obj/item/reagent_containers/food/snacks/grown/wheat - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" - attacktext = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" + attack_verb_continuous = "kicks" + attack_verb_simple = "kick" health = 25 maxHealth = 25 ventcrawler = VENTCRAWLER_ALWAYS @@ -358,6 +378,8 @@ gold_core_spawnable = FRIENDLY_SPAWN var/static/kiwi_count = 0 + footstep_type = FOOTSTEP_MOB_CLAW + /mob/living/simple_animal/kiwi/Destroy() --kiwi_count return ..() @@ -418,10 +440,14 @@ speak_chance = 2 turns_per_move = 2 butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" - attacktext = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" + attack_verb_continuous = "kicks" + attack_verb_simple = "kick" health = 10 maxHealth = 10 ventcrawler = VENTCRAWLER_ALWAYS @@ -430,6 +456,8 @@ mob_size = MOB_SIZE_TINY gold_core_spawnable = FRIENDLY_SPAWN + footstep_type = FOOTSTEP_MOB_CLAW + /mob/living/simple_animal/babyKiwi/Initialize() . = ..() pixel_x = rand(-6, 6) @@ -472,3 +500,33 @@ user.visible_message("[user] milks [src] using \the [O].", "You milk [src] using \the [O].") else to_chat(user, "The udder is dry. Wait a bit longer...") + +/mob/living/simple_animal/deer + name = "doe" + desc = "A gentle, peaceful forest animal. How did this get into space?" + icon_state = "deer-doe" + icon_living = "deer-doe" + icon_dead = "deer-doe-dead" + gender = FEMALE + mob_biotypes = MOB_ORGANIC|MOB_BEAST + speak = list("Weeeeeeee?","Weeee","WEOOOOOOOOOO") + speak_emote = list("grunts","grunts lowly") + emote_hear = list("brays.") + emote_see = list("shakes its head.") + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 3) + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently nudges" + response_disarm_simple = "gently nudge" + response_harm_continuous = "kicks" + response_harm_simple = "kick" + attack_verb_continuous = "bucks" + attack_verb_simple = "buck" + attack_sound = 'sound/weapons/punch1.ogg' + health = 75 + maxHealth = 75 + blood_volume = BLOOD_VOLUME_NORMAL + footstep_type = FOOTSTEP_MOB_SHOE \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/friendly/fox.dm b/code/modules/mob/living/simple_animal/friendly/fox.dm index 95b082b733..4e4fd7ccfc 100644 --- a/code/modules/mob/living/simple_animal/friendly/fox.dm +++ b/code/modules/mob/living/simple_animal/friendly/fox.dm @@ -14,11 +14,14 @@ turns_per_move = 5 see_in_dark = 6 butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 3) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" gold_core_spawnable = FRIENDLY_SPAWN - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_CLAW /mob/living/simple_animal/pet/fox/ComponentInitialize() . = ..() diff --git a/code/modules/mob/living/simple_animal/friendly/gondola.dm b/code/modules/mob/living/simple_animal/friendly/gondola.dm index 04d53e7d05..0cfea3548b 100644 --- a/code/modules/mob/living/simple_animal/friendly/gondola.dm +++ b/code/modules/mob/living/simple_animal/friendly/gondola.dm @@ -9,9 +9,12 @@ name = "gondola" real_name = "gondola" desc = "Gondola is the silent walker. Having no hands he embodies the Taoist principle of wu-wei (non-action) while his smiling facial expression shows his utter and complete acceptance of the world as it is. Its hide is extremely valuable." - response_help = "pets" - response_disarm = "bops" - response_harm = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "bops" + response_disarm_simple = "bop" + response_harm_continuous = "kicks" + response_harm_simple = "kick" faction = list("gondola") turns_per_move = 10 icon = 'icons/mob/gondolas.dmi' diff --git a/code/modules/mob/living/simple_animal/friendly/lizard.dm b/code/modules/mob/living/simple_animal/friendly/lizard.dm index 9ae46f29e5..b9ff99b677 100644 --- a/code/modules/mob/living/simple_animal/friendly/lizard.dm +++ b/code/modules/mob/living/simple_animal/friendly/lizard.dm @@ -8,12 +8,16 @@ health = 5 maxHealth = 5 faction = list("Lizard") - attacktext = "bites" + attack_verb_continuous = "bites" + attack_verb_simple = "bite" melee_damage_lower = 1 melee_damage_upper = 2 - response_help = "pets" - response_disarm = "shoos" - response_harm = "stomps on" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "shoos" + response_disarm_simple = "shoo" + response_harm_continuous = "stomps on" + response_harm_simple = "stomp on" ventcrawler = VENTCRAWLER_ALWAYS density = FALSE pass_flags = PASSTABLE | PASSMOB diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index 7f83bb9f9b..50d1e44d2a 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -15,9 +15,12 @@ maxHealth = 5 health = 5 butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 1) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "splats" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "splats" + response_harm_simple = "splat" density = FALSE ventcrawler = VENTCRAWLER_ALWAYS pass_flags = PASSTABLE | PASSGRILLE | PASSMOB @@ -103,9 +106,6 @@ GLOBAL_VAR(tom_existed) /mob/living/simple_animal/mouse/brown/Tom name = "Tom" desc = "Jerry the cat is not amused." - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "splats" gold_core_spawnable = NO_SPAWN /mob/living/simple_animal/mouse/brown/Tom/Initialize() diff --git a/code/modules/mob/living/simple_animal/friendly/panda.dm b/code/modules/mob/living/simple_animal/friendly/panda.dm index a7b6143ef5..7e523fea83 100644 --- a/code/modules/mob/living/simple_animal/friendly/panda.dm +++ b/code/modules/mob/living/simple_animal/friendly/panda.dm @@ -13,8 +13,11 @@ turns_per_move = 5 see_in_dark = 6 butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 3) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" gold_core_spawnable = FRIENDLY_SPAWN - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_CLAW diff --git a/code/modules/mob/living/simple_animal/friendly/penguin.dm b/code/modules/mob/living/simple_animal/friendly/penguin.dm index 9835840dbf..f92f4184b7 100644 --- a/code/modules/mob/living/simple_animal/friendly/penguin.dm +++ b/code/modules/mob/living/simple_animal/friendly/penguin.dm @@ -1,9 +1,12 @@ //Penguins /mob/living/simple_animal/pet/penguin - response_help = "pets" - response_disarm = "bops" - response_harm = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "bops" + response_disarm_simple = "bop" + response_harm_continuous = "kicks" + response_harm_simple = "kick" speak = list("Gah Gah!", "NOOT NOOT!", "NOOT!", "Noot", "noot", "Prah!", "Grah!") speak_emote = list("squawks", "gakkers") emote_hear = list("squawk!", "gakkers!", "noots.","NOOTS!") @@ -15,7 +18,7 @@ turns_per_move = 10 icon = 'icons/mob/penguins.dmi' - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_BAREFOOT /mob/living/simple_animal/pet/penguin/emperor name = "Emperor penguin" diff --git a/code/modules/mob/living/simple_animal/friendly/sloth.dm b/code/modules/mob/living/simple_animal/friendly/sloth.dm index 28063d6e52..83fe42a7a4 100644 --- a/code/modules/mob/living/simple_animal/friendly/sloth.dm +++ b/code/modules/mob/living/simple_animal/friendly/sloth.dm @@ -11,9 +11,12 @@ speak_chance = 1 turns_per_move = 5 butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 3) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" mob_biotypes = MOB_ORGANIC|MOB_BEAST gold_core_spawnable = FRIENDLY_SPAWN melee_damage_lower = 18 @@ -22,7 +25,7 @@ maxHealth = 50 speed = 10 glide_size = 2 - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_CLAW /mob/living/simple_animal/pet/fox/ComponentInitialize() . = ..() diff --git a/code/modules/mob/living/simple_animal/friendly/snake.dm b/code/modules/mob/living/simple_animal/friendly/snake.dm index 7f75888649..4d20b927a6 100644 --- a/code/modules/mob/living/simple_animal/friendly/snake.dm +++ b/code/modules/mob/living/simple_animal/friendly/snake.dm @@ -19,12 +19,16 @@ speak_emote = list("hisses") health = 20 maxHealth = 20 - attacktext = "bites" + attack_verb_continuous = "bites" + attack_verb_simple = "bite" melee_damage_lower = 5 melee_damage_upper = 6 - response_help = "pets" - response_disarm = "shoos" - response_harm = "steps on" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "shoos" + response_disarm_simple = "shoo" + response_harm_continuous = "steps on" + response_harm_simple = "step on" faction = list("hostile") ventcrawler = VENTCRAWLER_ALWAYS density = FALSE diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index d2794a3a78..9d94992747 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -13,9 +13,12 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians gender = NEUTER mob_biotypes = NONE bubble_icon = "guardian" - response_help = "passes through" - response_disarm = "flails at" - response_harm = "punches" + response_help_continuous = "passes through" + response_help_simple = "pass through" + response_disarm_continuous = "flails at" + response_disarm_simple = "flail at" + response_harm_continuous = "punches" + response_harm_simple = "punch" icon = 'icons/mob/guardian.dmi' icon_state = "magicbase" icon_living = "magicbase" @@ -29,7 +32,8 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 maxbodytemp = INFINITY - attacktext = "punches" + attack_verb_continuous = "punches" + attack_verb_simple = "punch" maxHealth = INFINITY //The spirit itself is invincible health = INFINITY healable = FALSE //don't brusepack the guardian @@ -109,7 +113,8 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians icon_dead = "holocarp" speak_emote = list("gnashes") desc = "A mysterious fish that stands by its charge, ever vigilant." - attacktext = "bites" + attack_verb_continuous = "bites" + attack_verb_simple = "bite" attack_sound = 'sound/weapons/bite.ogg' recolorentiresprite = TRUE if(!recolorentiresprite) //we want this to proc before stand logs in, so the overlay isnt gone for some reason diff --git a/code/modules/mob/living/simple_animal/guardian/types/assassin.dm b/code/modules/mob/living/simple_animal/guardian/types/assassin.dm index e507a4c831..e82d6cd16a 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/assassin.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/assassin.dm @@ -1,6 +1,7 @@ //Assassin /mob/living/simple_animal/hostile/guardian/assassin - attacktext = "slashes" + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" attack_sound = 'sound/weapons/bladeslice.ogg' damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) playstyle_string = "As an assassin type you do medium damage and have no damage resistance, but can enter stealth, massively increasing the damage of your next attack and causing it to ignore armor. Stealth is broken when you attack or take damage." diff --git a/code/modules/mob/living/simple_animal/guardian/types/charger.dm b/code/modules/mob/living/simple_animal/guardian/types/charger.dm index 1ece6dde37..c60e43ff01 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/charger.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/charger.dm @@ -54,7 +54,7 @@ var/blocked = FALSE if(hasmatchingsummoner(hit_atom)) //if the summoner matches don't hurt them blocked = TRUE - if(L.run_block(src, 90, "[name]", ATTACK_TYPE_TACKLE, 0, src) & BLOCK_SUCCESS) + if(L.mob_run_block(src, 90, "[name]", ATTACK_TYPE_TACKLE, 0, src, null, null) & BLOCK_SUCCESS) blocked = TRUE if(!blocked) L.drop_all_held_items() diff --git a/code/modules/mob/living/simple_animal/guardian/types/fire.dm b/code/modules/mob/living/simple_animal/guardian/types/fire.dm index 718bfd71af..97003a53e2 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/fire.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/fire.dm @@ -4,7 +4,8 @@ melee_damage_lower = 10 melee_damage_upper = 10 attack_sound = 'sound/items/welder.ogg' - attacktext = "ignites" + attack_verb_continuous = "ignites" + attack_verb_simple = "ignite" melee_damage_type = BURN damage_coeff = list(BRUTE = 0.7, BURN = 0.1, TOX = 0.7, CLONE = 0.7, STAMINA = 0, OXY = 0.7) playstyle_string = "As a chaos type, you take 30% damage reduction to all but burn, which you are almost immune to. You will ignite any enemy you bump into. in addition, your melee attacks will cause human targets to see everyone as you." diff --git a/code/modules/mob/living/simple_animal/guardian/types/lightning.dm b/code/modules/mob/living/simple_animal/guardian/types/lightning.dm index 7b7651822a..a1552f6648 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/lightning.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/lightning.dm @@ -6,7 +6,8 @@ /mob/living/simple_animal/hostile/guardian/beam melee_damage_lower = 10 melee_damage_upper = 10 - attacktext = "shocks" + attack_verb_continuous = "shocks" + attack_verb_simple = "shock" melee_damage_type = BURN attack_sound = 'sound/machines/defib_zap.ogg' damage_coeff = list(BRUTE = 0.7, BURN = 0.7, TOX = 0.7, CLONE = 0.7, STAMINA = 0, OXY = 0.7) diff --git a/code/modules/mob/living/simple_animal/guardian/types/ranged.dm b/code/modules/mob/living/simple_animal/guardian/types/ranged.dm index 539ee9081b..1746936ba3 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/ranged.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/ranged.dm @@ -8,7 +8,8 @@ /mob/living/simple_animal/hostile/guardian/ranged a_intent = INTENT_HELP - friendly = "quietly assesses" + friendly_verb_continuous = "quietly assesses" + friendly_verb_simple = "quietly assess" melee_damage_lower = 10 melee_damage_upper = 10 damage_coeff = list(BRUTE = 0.9, BURN = 0.9, TOX = 0.9, CLONE = 0.9, STAMINA = 0, OXY = 0.9) diff --git a/code/modules/mob/living/simple_animal/guardian/types/support.dm b/code/modules/mob/living/simple_animal/guardian/types/support.dm index 7b519e1ca1..21460b5c6b 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/support.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/support.dm @@ -1,7 +1,8 @@ //Healer /mob/living/simple_animal/hostile/guardian/healer a_intent = INTENT_HARM - friendly = "heals" + friendly_verb_continuous = "heals" + friendly_verb_simple = "heal" damage_coeff = list(BRUTE = 0.7, BURN = 0.7, TOX = 0.7, CLONE = 0.7, STAMINA = 0, OXY = 0.7) playstyle_string = "As a support type, you have 30% damage reduction and may toggle your basic attacks to a healing mode. In addition, Alt-Clicking on an adjacent object or mob will warp them to your bluespace beacon after a short delay." magic_fluff_string = "..And draw the CMO, a potent force of life... and death." diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index 2045e194d2..7120ab6d0a 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -8,9 +8,12 @@ icon_gib = "syndicate_gib" gender = FEMALE threat = 1 - response_help = "pokes" - response_disarm = "shoves" - response_harm = "hits" + response_help_continuous = "pokes" + response_help_simple = "poke" + response_disarm_continuous = "shoves" + response_disarm_simple = "shove" + response_harm_continuous = "hits" + response_harm_simple = "hit" speed = 0 butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/xeno = 4, /obj/item/stack/sheet/animalhide/xeno = 1) @@ -20,7 +23,8 @@ obj_damage = 60 melee_damage_lower = 25 melee_damage_upper = 25 - attacktext = "slashes" + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" speak_emote = list("hisses") bubble_icon = "alien" a_intent = INTENT_HARM @@ -37,7 +41,9 @@ death_sound = 'sound/voice/hiss6.ogg' deathmessage = "lets out a waning guttural screech, green blood bubbling from its maw..." - do_footstep = TRUE +/mob/living/simple_animal/hostile/alien/Initialize() + . = ..() + AddComponent(/datum/component/footstep, FOOTSTEP_MOB_CLAW) /mob/living/simple_animal/hostile/alien/drone name = "alien drone" @@ -80,6 +86,7 @@ icon_state = "alienq" icon_living = "alienq" icon_dead = "alienq_dead" + pixel_x = -16 threat = 8 health = 250 maxHealth = 250 @@ -162,7 +169,8 @@ melee_damage_upper = 0 threat = -1 a_intent = INTENT_HELP - friendly = "caresses" + friendly_verb_continuous = "caresses" + friendly_verb_simple = "caress" obj_damage = 0 environment_smash = ENVIRONMENT_SMASH_NONE gold_core_spawnable = HOSTILE_SPAWN diff --git a/code/modules/mob/living/simple_animal/hostile/banana_spider.dm b/code/modules/mob/living/simple_animal/hostile/banana_spider.dm index f3ce343bfd..259c0bc721 100644 --- a/code/modules/mob/living/simple_animal/hostile/banana_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/banana_spider.dm @@ -13,14 +13,16 @@ maxbodytemp = INFINITY pass_flags = PASSTABLE | PASSGRILLE | PASSMOB mob_size = MOB_SIZE_TINY - response_help = "pokes" - response_disarm = "shoos" - response_harm = "splats" + response_help_continuous = "pokes" + response_help_simple = "poke" + response_disarm_continuous = "shoos" + response_disarm_simple = "shoo" + response_harm_continuous = "splats" + response_harm_simple = "plat" speak_emote = list("chitters") mouse_opacity = 2 density = TRUE ventcrawler = VENTCRAWLER_ALWAYS - gold_core_spawnable = FRIENDLY_SPAWN verb_say = "chitters" verb_ask = "chitters inquisitively" verb_exclaim = "chitters loudly" diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index a77098cb80..0e864a1e37 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -17,9 +17,12 @@ turns_per_move = 5 see_in_dark = 6 butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/bear = 5, /obj/item/clothing/head/bearpelt = 1) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "hits" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" maxHealth = 60 health = 60 spacewalk = TRUE @@ -28,9 +31,11 @@ obj_damage = 60 melee_damage_lower = 20 melee_damage_upper = 30 - attacktext = "claws" + attack_verb_continuous = "claws" + attack_verb_simple = "claw" attack_sound = 'sound/weapons/bladeslice.ogg' - friendly = "bear hugs" + friendly_verb_continuous = "bear hugs" + friendly_verb_simple = "bear hug" //Space bears aren't affected by cold. atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) @@ -40,7 +45,7 @@ faction = list("russian") gold_core_spawnable = HOSTILE_SPAWN - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_CLAW //SPACE BEARS! SQUEEEEEEEE~ OW! FUCK! IT BIT MY HAND OFF!! /mob/living/simple_animal/hostile/bear/Hudson @@ -111,12 +116,14 @@ mob/living/simple_animal/hostile/bear/butter //The mighty companion to Cak. Seve melee_damage_lower = 1 melee_damage_upper = 1 armour_penetration = 0 - response_harm = "takes a bite out of" + response_harm_continuous = "takes a bite out of" + response_harm_simple = "take a bite out of" attacked_sound = 'sound/items/eatfood.ogg' deathmessage = "loses its false life and collapses!" butcher_results = list(/obj/item/reagent_containers/food/snacks/butter = 6, /obj/item/reagent_containers/food/snacks/meat/slab = 3, /obj/item/organ/brain = 1, /obj/item/organ/heart = 1) attack_sound = 'sound/weapons/slap.ogg' - attacktext = "slaps" + attack_verb_continuous = "slaps" + attack_verb_simple = "slap" /mob/living/simple_animal/hostile/bear/butter/Life() //Heals butter bear really fast when he takes damage. if(stat) diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm index f5454933c8..5f3d4f11c1 100644 --- a/code/modules/mob/living/simple_animal/hostile/bees.dm +++ b/code/modules/mob/living/simple_animal/hostile/bees.dm @@ -23,10 +23,14 @@ turns_per_move = 0 melee_damage_lower = 1 melee_damage_upper = 1 - attacktext = "stings" - response_help = "shoos" - response_disarm = "swats away" - response_harm = "squashes" + attack_verb_continuous = "stings" + attack_verb_simple = "sting" + response_help_continuous = "shoos" + response_help_simple = "shoo" + response_disarm_continuous = "swats away" + response_disarm_simple = "swat away" + response_harm_continuous = "squashes" + response_harm_simple = "squash" maxHealth = 10 health = 10 spacewalk = TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm index dbb957a96b..b1a4f05e8c 100644 --- a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm +++ b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm @@ -7,6 +7,7 @@ status_flags = 0 a_intent = INTENT_HARM gender = NEUTER + has_field_of_vision = FALSE //You are a frikkin boss var/list/boss_abilities = list() //list of /datum/action/boss var/datum/boss_active_timed_battle/atb var/point_regen_delay = 1 diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm index 07572fff83..aef3fb714d 100644 --- a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm @@ -23,7 +23,7 @@ attack_sound = 'sound/hallucinations/growl1.ogg' var/list/copies = list() - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_SHOE //Summon Ability diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index ced56f0705..a56a8dcc29 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -12,9 +12,10 @@ speak_chance = 0 turns_per_move = 5 butcher_results = list(/obj/item/reagent_containers/food/snacks/carpmeat = 2) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "hits" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" emote_taunt = list("gnashes") taunt_chance = 30 speed = 0 @@ -25,7 +26,8 @@ obj_damage = 50 melee_damage_lower = 15 melee_damage_upper = 15 - attacktext = "bites" + attack_verb_continuous = "bites" + attack_verb_simple = "bite" attack_sound = 'sound/weapons/bite.ogg' speak_emote = list("gnashes") //Space carp aren't affected by cold. diff --git a/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm b/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm index 4e3375caf7..d85f75cbbd 100644 --- a/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm +++ b/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm @@ -8,9 +8,6 @@ icon_gib = "syndicate_gib" speak_chance = 0 turns_per_move = 5 - response_help = "pokes" - response_disarm = "shoves" - response_harm = "hits" speed = 0 stat_attack = UNCONSCIOUS robust_searching = 1 @@ -19,7 +16,8 @@ harm_intent_damage = 5 melee_damage_lower = 15 melee_damage_upper = 15 - attacktext = "slashes at" + attack_verb_continuous = "slashes at" + attack_verb_simple = "slash at" attack_sound = 'sound/weapons/circsawhit.ogg' a_intent = INTENT_HARM mob_biotypes = MOB_ORGANIC|MOB_HUMANOID diff --git a/code/modules/mob/living/simple_animal/hostile/creature.dm b/code/modules/mob/living/simple_animal/hostile/creature.dm deleted file mode 100644 index bba37f94af..0000000000 --- a/code/modules/mob/living/simple_animal/hostile/creature.dm +++ /dev/null @@ -1,18 +0,0 @@ -/mob/living/simple_animal/hostile/creature - name = "creature" - desc = "A sanity-destroying otherthing." - icon_state = "otherthing" - icon_living = "otherthing" - icon_dead = "otherthing-dead" - health = 80 - maxHealth = 80 - obj_damage = 100 - melee_damage_lower = 25 - melee_damage_upper = 50 - attacktext = "chomps" - attack_sound = 'sound/weapons/bite.ogg' - faction = list("creature") - speak_emote = list("screams") - gold_core_spawnable = HOSTILE_SPAWN - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm b/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm index 6ca6eac0cc..48266e3e76 100644 --- a/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm @@ -17,7 +17,8 @@ obj_damage = 20 melee_damage_lower = 5 melee_damage_upper = 5 - attacktext = "staves" + attack_verb_continuous = "staves" + attack_verb_simple = "stave" a_intent = INTENT_HARM speak_emote = list("chants") attack_sound = 'sound/weapons/bladeslice.ogg' @@ -25,7 +26,7 @@ turns_per_move = 5 gold_core_spawnable = HOSTILE_SPAWN faction = list(ROLE_WIZARD) - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_SHOE weather_immunities = list("lava","ash") minbodytemp = 0 maxbodytemp = INFINITY diff --git a/code/modules/mob/living/simple_animal/hostile/eyeballs.dm b/code/modules/mob/living/simple_animal/hostile/eyeballs.dm index dbb9048ca4..75e8c55236 100644 --- a/code/modules/mob/living/simple_animal/hostile/eyeballs.dm +++ b/code/modules/mob/living/simple_animal/hostile/eyeballs.dm @@ -8,9 +8,10 @@ icon_gib = "" gender = NEUTER mob_biotypes = MOB_ORGANIC - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "hits" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" emote_taunt = list("glares") taunt_chance = 25 maxHealth = 45 @@ -21,9 +22,11 @@ obj_damage = 60 melee_damage_lower = 20 melee_damage_upper = 25 - attacktext = "blinks at" + attack_verb_continuous = "blinks at" + attack_verb_simple = "blink at" attack_sound = 'sound/weapons/pierce.ogg' movement_type = FLYING faction = list("spooky") del_on_death = 1 + field_of_vision_type = FOV_270_DEGREES //Obviously, it's one eyeball. diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm index 7ac0ea2b44..4f8d2fef6c 100644 --- a/code/modules/mob/living/simple_animal/hostile/faithless.dm +++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm @@ -9,9 +9,12 @@ gender = MALE speak_chance = 0 turns_per_move = 5 - response_help = "passes through" - response_disarm = "shoves" - response_harm = "hits" + response_help_continuous = "passes through" + response_help_simple = "pass through" + response_disarm_continuous = "shoves" + response_disarm_simple = "shove" + response_harm_continuous = "hits" + response_harm_simple = "hit" emote_taunt = list("wails") taunt_chance = 25 speed = 0 @@ -26,7 +29,8 @@ obj_damage = 50 melee_damage_lower = 15 melee_damage_upper = 15 - attacktext = "grips" + attack_verb_continuous = "grips" + attack_verb_simple = "grip" attack_sound = 'sound/hallucinations/growl1.ogg' speak_emote = list("growls") @@ -36,7 +40,7 @@ faction = list("faithless") gold_core_spawnable = HOSTILE_SPAWN - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_SHOE /mob/living/simple_animal/hostile/faithless/AttackingTarget() . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index f19aa0a2a7..a253ecfd96 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -30,9 +30,12 @@ turns_per_move = 5 see_in_dark = 10 butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/spider = 2, /obj/item/reagent_containers/food/snacks/spiderleg = 8) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "hits" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" maxHealth = 200 health = 200 obj_damage = 60 @@ -43,18 +46,19 @@ pass_flags = PASSTABLE move_to_delay = 6 ventcrawler = VENTCRAWLER_ALWAYS - attacktext = "bites" + attack_verb_continuous = "bites" + attack_verb_simple = "bite" attack_sound = 'sound/weapons/bite.ogg' unique_name = 1 gold_core_spawnable = HOSTILE_SPAWN see_in_dark = 4 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE + footstep_type = FOOTSTEP_MOB_CLAW + has_field_of_vision = FALSE // 360° vision. var/playable_spider = FALSE var/datum/action/innate/spider/lay_web/lay_web var/directive = "" //Message passed down to children, to relay the creator's orders - do_footstep = TRUE - /mob/living/simple_animal/hostile/poison/giant_spider/Initialize() . = ..() lay_web = new diff --git a/code/modules/mob/living/simple_animal/hostile/goose.dm b/code/modules/mob/living/simple_animal/hostile/goose.dm index db232c20c4..1dcb13aa9b 100644 --- a/code/modules/mob/living/simple_animal/hostile/goose.dm +++ b/code/modules/mob/living/simple_animal/hostile/goose.dm @@ -10,9 +10,12 @@ speak_chance = 0 turns_per_move = 5 butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" emote_taunt = list("hisses") taunt_chance = 30 speed = 0 @@ -21,7 +24,8 @@ harm_intent_damage = 5 melee_damage_lower = 5 melee_damage_upper = 5 - attacktext = "pecks" + attack_verb_continuous = "pecks" + attack_verb_simple = "peck" attack_sound = "goose" speak_emote = list("honks") faction = list("neutral") diff --git a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm index 7c6f9e9c7b..f48eef083b 100644 --- a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm +++ b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm @@ -16,16 +16,20 @@ health = 220 loot = list(/obj/effect/gibspawner/generic) butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/gorilla = 4) - response_help = "prods" - response_disarm = "challenges" - response_harm = "thumps" + response_help_continuous = "prods" + response_help_simple = "prod" + response_disarm_continuous = "challenges" + response_disarm_simple = "challenge" + response_harm_continuous = "thumps" + response_harm_simple = "thump" speed = 1 melee_damage_lower = 15 melee_damage_upper = 18 damage_coeff = list(BRUTE = 1, BURN = 1.5, TOX = 1.5, CLONE = 0, STAMINA = 0, OXY = 1.5) obj_damage = 20 environment_smash = ENVIRONMENT_SMASH_WALLS - attacktext = "pummels" + attack_verb_continuous = "pummels" + attack_verb_simple = "pummel" attack_sound = 'sound/weapons/punch1.ogg' dextrous = TRUE held_items = list(null, null) @@ -39,7 +43,7 @@ var/list/gorilla_overlays[GORILLA_TOTAL_LAYERS] var/oogas = 0 - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_BAREFOOT // Gorillas like to dismember limbs from unconcious mobs. // Returns null when the target is not an unconcious carbon mob; a list of limbs (possibly empty) otherwise. diff --git a/code/modules/mob/living/simple_animal/hostile/headcrab.dm b/code/modules/mob/living/simple_animal/hostile/headcrab.dm index 9d64b76198..501534237a 100644 --- a/code/modules/mob/living/simple_animal/hostile/headcrab.dm +++ b/code/modules/mob/living/simple_animal/hostile/headcrab.dm @@ -12,7 +12,8 @@ maxHealth = 50 melee_damage_lower = 5 melee_damage_upper = 5 - attacktext = "chomps" + attack_verb_continuous = "chomps" + attack_verb_simple = "chomp" attack_sound = 'sound/weapons/bite.ogg' faction = list("creature") robust_searching = 1 diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm index 1cc675825f..b627bf67c2 100644 --- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm +++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm @@ -16,7 +16,8 @@ healable = 0 melee_damage_lower = 10 melee_damage_upper = 10 - attacktext = "saw" + attack_verb_continuous = "saw" + attack_verb_simple = "saw" attack_sound = 'sound/weapons/bladeslice.ogg' projectilesound = 'sound/weapons/gunshot.ogg' projectiletype = /obj/item/projectile/hivebotbullet @@ -30,7 +31,7 @@ loot = list(/obj/effect/decal/cleanable/robot_debris) blood_volume = 0 - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_CLAW /mob/living/simple_animal/hostile/hivebot/Initialize() . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/illusion.dm b/code/modules/mob/living/simple_animal/hostile/illusion.dm index 89303702f3..cab87010ef 100644 --- a/code/modules/mob/living/simple_animal/hostile/illusion.dm +++ b/code/modules/mob/living/simple_animal/hostile/illusion.dm @@ -10,7 +10,8 @@ melee_damage_lower = 5 melee_damage_upper = 5 a_intent = INTENT_HARM - attacktext = "gores" + attack_verb_continuous = "gores" + attack_verb_simple = "gore" maxHealth = 100 health = 100 speed = 0 @@ -20,6 +21,7 @@ var/multiply_chance = 0 //if we multiply on hit del_on_death = 1 deathmessage = "vanishes into thin air! It was a fake!" + has_field_of_vision = FALSE //not meant to be played anyway. /mob/living/simple_animal/hostile/illusion/Life() diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/_jungle_mobs.dm b/code/modules/mob/living/simple_animal/hostile/jungle/_jungle_mobs.dm index c337344c90..c2b553aad7 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/_jungle_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/_jungle_mobs.dm @@ -7,9 +7,8 @@ environment_smash = ENVIRONMENT_SMASH_WALLS minbodytemp = 0 maxbodytemp = 450 - response_help = "pokes" - response_disarm = "shoves" - response_harm = "strikes" + response_harm_continuous = "strikes" + response_harm_simple = "strike" status_flags = NONE a_intent = INTENT_HARM see_in_dark = 4 diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm index 05c4007b6f..574811c968 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm @@ -27,7 +27,7 @@ var/hop_cooldown = 0 //Strictly for player controlled leapers var/projectile_ready = FALSE //Stopping AI leapers from firing whenever they want, and only doing it after a hop has finished instead - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_HEAVY /obj/item/projectile/leaper name = "leaper bubble" diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm b/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm index ae161d596d..40274c0029 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/mega_arachnid.dm @@ -25,7 +25,7 @@ projectilesound = 'sound/weapons/pierce.ogg' alpha = 50 - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_CLAW /mob/living/simple_animal/hostile/jungle/mega_arachnid/Life() ..() diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm index c05d14965e..6efa0cf468 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm @@ -32,7 +32,7 @@ var/attack_state = MOOK_ATTACK_NEUTRAL var/struck_target_leap = FALSE - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_BAREFOOT /mob/living/simple_animal/hostile/jungle/mook/CanPass(atom/movable/O) if(istype(O, /mob/living/simple_animal/hostile/jungle/mook)) diff --git a/code/modules/mob/living/simple_animal/hostile/killertomato.dm b/code/modules/mob/living/simple_animal/hostile/killertomato.dm index e418cc4ab0..9cb65d7c30 100644 --- a/code/modules/mob/living/simple_animal/hostile/killertomato.dm +++ b/code/modules/mob/living/simple_animal/hostile/killertomato.dm @@ -12,12 +12,16 @@ health = 30 see_in_dark = 3 butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/killertomato = 2) - response_help = "prods" - response_disarm = "pushes aside" - response_harm = "smacks" + response_help_continuous = "prods" + response_help_simple = "prod" + response_disarm_continuous = "pushes aside" + response_disarm_simple = "push aside" + response_harm_continuous = "smacks" + response_harm_simple = "smack" melee_damage_lower = 8 melee_damage_upper = 12 - attacktext = "slams" + attack_verb_continuous = "slams" + attack_verb_simple = "slam" attack_sound = 'sound/weapons/punch1.ogg' ventcrawler = VENTCRAWLER_ALWAYS faction = list("plants") diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm index fd278eb438..3ef4ef9be9 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm @@ -54,7 +54,7 @@ Difficulty: Medium deathmessage = "falls to the ground, decaying into glowing particles." death_sound = "bodyfall" - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_HEAVY /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/guidance guidance = TRUE @@ -75,7 +75,7 @@ Difficulty: Medium /obj/item/projectile/kinetic/miner damage = 40 - speed = 0.9 + pixels_per_second = TILES_TO_PIXELS(11.111) icon_state = "ka_tracer" range = MINER_DASH_RANGE diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm index d2680fbf61..fe6c2290c4 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -29,12 +29,14 @@ Difficulty: Hard threat = 35 health = 2500 maxHealth = 2500 - attacktext = "rends" + attack_verb_continuous = "rends" + attack_verb_simple = "rend" attack_sound = 'sound/magic/demon_attack1.ogg' icon_state = "bubblegum" icon_living = "bubblegum" icon_dead = "" - friendly = "stares down" + friendly_verb_continuous = "stares down" + friendly_verb_simple = "stare down" icon = 'icons/mob/lavaland/96x96megafauna.dmi' speak_emote = list("gurgles") armour_penetration = 40 @@ -55,7 +57,7 @@ Difficulty: Hard deathmessage = "sinks into a pool of blood, fleeing the battle. You've won, for now... " death_sound = 'sound/magic/enter_blood.ogg' - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_HEAVY /obj/item/gps/internal/bubblegum icon_state = null @@ -227,11 +229,13 @@ Difficulty: Hard icon_state = "bloodbrood" icon_living = "bloodbrood" icon_aggro = "bloodbrood" - attacktext = "pierces" + attack_verb_continuous = "pierces" + attack_verb_simple = "pierce" color = "#C80000" density = FALSE faction = list("mining", "boss") weather_immunities = list("lava","ash") + has_field_of_vision = FALSE /mob/living/simple_animal/hostile/asteroid/hivelordbrood/slaughter/CanPass(atom/movable/mover, turf/target) if(istype(mover, /mob/living/simple_animal/hostile/megafauna/bubblegum)) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 73fb9d4e48..04ff9413aa 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -27,12 +27,14 @@ Difficulty: Very Hard threat = 40 health = 2500 maxHealth = 2500 - attacktext = "judges" + attack_verb_continuous = "judges" + attack_verb_simple = "judge" attack_sound = 'sound/magic/clockwork/ratvar_attack.ogg' icon_state = "eva" icon_living = "eva" icon_dead = "dragon_dead" - friendly = "stares down" + friendly_verb_continuous = "stares down" + friendly_verb_simple = "stare down" icon = 'icons/mob/lavaland/96x96megafauna.dmi' speak_emote = list("roars") armour_penetration = 40 @@ -210,7 +212,7 @@ Difficulty: Very Hard icon_state= "chronobolt" damage = 25 armour_penetration = 100 - speed = 2 + pixels_per_second = TILES_TO_PIXELS(5) eyeblur = 0 damage_type = BRUTE pass_flags = PASSTABLE @@ -606,14 +608,18 @@ Difficulty: Very Hard icon_dead = "butterfly_dead" threat = -0.7 turns_per_move = 1 - response_help = "waves away" - response_disarm = "brushes aside" - response_harm = "disrupts" + response_help_continuous = "waves away" + response_help_simple = "wave away" + response_disarm_continuous = "brushes aside" + response_disarm_simple = "brush aside" + response_harm_continuous = "disrupts" + response_harm_simple = "disrupt" speak_emote = list("oscillates") maxHealth = 2 health = 2 harm_intent_damage = 1 - friendly = "mends" + friendly_verb_continuous = "mends" + friendly_verb_simple = "mend" density = FALSE movement_type = FLYING pass_flags = PASSTABLE | PASSGRILLE | PASSMOB diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm index 3d106021de..5e866f95f1 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm @@ -10,7 +10,8 @@ Difficulty: Extremely Hard icon_state = "demonic_miner" icon_living = "demonic_miner" icon = 'icons/mob/icemoon/icemoon_monsters.dmi' - attacktext = "pummels" + attack_verb_continuous = "pummels" + attack_verb_simple = "pummel" attack_sound = 'sound/weapons/sonic_jackhammer.ogg' mob_biotypes = MOB_ORGANIC|MOB_HUMANOID light_color = "#E4C7C5" @@ -70,7 +71,10 @@ Difficulty: Extremely Hard /mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/OpenFire() check_enraged() - projectile_speed_multiplier = 1 - enraged * 0.25 + if(enraged) + projectile_speed_multiplier = 1.33 + else + projectile_speed_multiplier = 1 SetRecoveryTime(100, 100) if(client) @@ -108,7 +112,7 @@ Difficulty: Extremely Hard icon_state = "ice_1" damage = 20 armour_penetration = 100 - speed = 10 + pixels_per_second = TILES_TO_PIXELS(1) homing_turn_speed = 30 damage_type = BURN @@ -122,7 +126,7 @@ Difficulty: Extremely Hard icon_state = "nuclear_particle" damage = 5 armour_penetration = 100 - speed = 4 + pixels_per_second = TILES_TO_PIXELS(2.5) damage_type = BRUTE /obj/item/projectile/ice_blast @@ -130,7 +134,7 @@ Difficulty: Extremely Hard icon_state = "ice_2" damage = 15 armour_penetration = 100 - speed = 4 + pixels_per_second = TILES_TO_PIXELS(2.5) damage_type = BRUTE /obj/item/projectile/ice_blast/on_hit(atom/target, blocked = FALSE) @@ -184,7 +188,7 @@ Difficulty: Extremely Hard if(!startloc || !endloc) break var/obj/item/projectile/ice_blast/P = new(startloc) - P.speed *= projectile_speed_multiplier + P.pixels_per_second *= projectile_speed_multiplier P.preparePixelProjectile(endloc, startloc, null, angle + rand(-10, 10)) P.firer = firer if(original) @@ -200,7 +204,7 @@ Difficulty: Extremely Hard if(!endloc) break var/obj/item/projectile/P = new /obj/item/projectile/snowball(startloc) - P.speed *= projectile_speed_multiplier + P.pixels_per_second *= projectile_speed_multiplier P.preparePixelProjectile(endloc, startloc, null, rand(-spread, spread)) P.firer = src if(target) @@ -219,7 +223,7 @@ Difficulty: Extremely Hard if(!endloc) break var/obj/item/projectile/P = new /obj/item/projectile/ice_blast(startloc) - P.speed *= projectile_speed_multiplier + P.pixels_per_second *= projectile_speed_multiplier P.preparePixelProjectile(endloc, startloc, null, spread) P.firer = src if(target) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index c59272214b..062a4c9a43 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -37,13 +37,15 @@ Difficulty: Medium health = 2500 maxHealth = 2500 spacewalk = TRUE - attacktext = "chomps" + attack_verb_continuous = "chomps" + attack_verb_simple = "chomp" attack_sound = 'sound/magic/demon_attack1.ogg' icon = 'icons/mob/lavaland/64x64megafauna.dmi' icon_state = "dragon" icon_living = "dragon" icon_dead = "dragon_dead" - friendly = "stares down" + friendly_verb_continuous = "stares down" + friendly_verb_simple = "stare down" speak_emote = list("roars") armour_penetration = 40 melee_damage_lower = 40 @@ -64,7 +66,7 @@ Difficulty: Medium death_sound = 'sound/magic/demon_dies.ogg' var/datum/action/small_sprite/smallsprite = new/datum/action/small_sprite/drake() - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_HEAVY /mob/living/simple_animal/hostile/megafauna/dragon/Initialize() smallsprite.Grant(src) @@ -81,7 +83,7 @@ Difficulty: Medium return FALSE return ..() -/mob/living/simple_animal/hostile/megafauna/dragon/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs) +/mob/living/simple_animal/hostile/megafauna/dragon/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, mob/target, target_message) if(swooping & SWOOP_INVULNERABLE) //to suppress attack messages without overriding every single proc that could send a message saying we got hit return return ..() 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 477c2ce3aa..4ade831f95 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -40,11 +40,13 @@ Difficulty: Normal threat = 30 health = 2500 maxHealth = 2500 - attacktext = "clubs" + attack_verb_continuous = "clubs" + attack_verb_simple = "club" attack_sound = 'sound/weapons/sonic_jackhammer.ogg' icon_state = "hierophant" icon_living = "hierophant" - friendly = "stares down" + friendly_verb_continuous = "stares down" + friendly_verb_simple = "stare down" icon = 'icons/mob/lavaland/hierophant_new.dmi' faction = list("boss") //asteroid mobs? get that shit out of my beautiful square house speak_emote = list("preaches") diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm index 62a09dff65..4da8a90b23 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm @@ -26,7 +26,8 @@ Difficulty: Medium icon_living = "legion" desc = "One of many." icon = 'icons/mob/lavaland/legion.dmi' - attacktext = "chomps" + attack_verb_continuous = "chomps" + attack_verb_simple = "chomp" attack_sound = 'sound/magic/demon_attack1.ogg' speak_emote = list("echoes") armour_penetration = 50 diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index 78987ebaa0..02e1b47c95 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -27,6 +27,7 @@ mob_size = MOB_SIZE_LARGE layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1 + has_field_of_vision = FALSE //You are a frikkin boss /// Crusher loot dropped when fauna killed with a crusher var/list/crusher_loot var/medal_type @@ -144,6 +145,7 @@ /mob/living/simple_animal/hostile/megafauna/proc/SetRecoveryTime(buffer_time) recovery_time = world.time + buffer_time + ranged_cooldown = max(ranged_cooldown, world.time + buffer_time) // CITADEL BANDAID FIX FOR MEGAFAUNA NOT RESPECTING RECOVERY TIME. /mob/living/simple_animal/hostile/megafauna/proc/grant_achievement(medaltype, scoretype, crusher_kill) if(!medal_type || (flags_1 & ADMIN_SPAWNED_1)) //Don't award medals if the medal type isn't set diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm index 5ed163ae7e..ed189f052d 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm @@ -11,7 +11,8 @@ Difficulty: Hard icon_living = "wendigo" icon_dead = "wendigo_dead" icon = 'icons/mob/icemoon/64x64megafauna.dmi' - attacktext = "claws" + attack_verb_continuous = "claws" + attack_verb_simple = "claw" attack_sound = 'sound/magic/demon_attack1.ogg' weather_immunities = list("snow") speak_emote = list("roars") diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index 138d7f155e..5afe109550 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -5,9 +5,12 @@ icon_state = "crate" icon_living = "crate" - response_help = "touches" - response_disarm = "pushes" - response_harm = "hits" + response_help_continuous = "touches" + response_help_simple = "touch" + response_disarm_continuous = "pushes" + response_disarm_simple = "push" + response_harm_continuous = "hits" + response_harm_simple = "hit" speed = 0 maxHealth = 250 health = 250 @@ -18,7 +21,8 @@ harm_intent_damage = 5 melee_damage_lower = 8 melee_damage_upper = 12 - attacktext = "attacks" + attack_verb_continuous = "attacks" + attack_verb_simple = "attack" attack_sound = 'sound/weapons/punch1.ogg' emote_taunt = list("growls") speak_emote = list("creaks") @@ -34,7 +38,8 @@ // Aggro when you try to open them. Will also pickup loot when spawns and drop it when dies. /mob/living/simple_animal/hostile/mimic/crate - attacktext = "bites" + attack_verb_continuous = "bites" + attack_verb_simple = "bite" speak_emote = list("clatters") stop_automated_movement = 1 wander = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm index 4d20d4c7fb..306011dc80 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm @@ -25,7 +25,8 @@ obj_damage = 60 melee_damage_lower = 12 melee_damage_upper = 12 - attacktext = "bites into" + attack_verb_continuous = "bites into" + attack_verb_simple = "bite into" a_intent = INTENT_HARM speak_emote = list("chitters") attack_sound = 'sound/weapons/bladeslice.ogg' @@ -72,7 +73,8 @@ throw_message = "bounces harmlessly off of" melee_damage_lower = 15 melee_damage_upper = 15 - attacktext = "impales" + attack_verb_continuous = "impales" + attack_verb_simple = "impale" a_intent = INTENT_HARM speak_emote = list("telepathically cries") attack_sound = 'sound/weapons/bladeslice.ogg' @@ -82,6 +84,32 @@ crusher_loot = /obj/item/crusher_trophy/watcher_wing loot = list() butcher_results = list(/obj/item/stack/ore/diamond = 2, /obj/item/stack/sheet/sinew = 2, /obj/item/stack/sheet/bone = 1) + search_objects = 1 + wanted_objects = list(/obj/item/pen/survival, /obj/item/stack/ore/diamond) + field_of_vision_type = FOV_270_DEGREES //Obviously, it's one eyeball. + +/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/Life() + . = ..() + if(stat == CONSCIOUS) + consume_bait() + +/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/proc/consume_bait() + var/obj/item/stack/ore/diamond/diamonds = locate(/obj/item/stack/ore/diamond) in oview(src, 9) + var/obj/item/pen/survival/bait = locate(/obj/item/pen/survival) in oview(src, 9) + if(!diamonds && !bait) + return + if(diamonds) + var/distanced = 0 + distanced = get_dist(loc,diamonds.loc) + if(distanced <= 1 && diamonds) + qdel(diamonds) + src.visible_message("[src] consumes [diamonds], and it disappears! ...At least, you think.") + if(bait) + var/distanceb = 0 + distanceb = get_dist(loc,bait.loc) + if(distanceb <= 1 && bait) + qdel(bait) + visible_message("[src] examines [bait] closer, and telekinetically shatters the pen.") /mob/living/simple_animal/hostile/asteroid/basilisk/watcher/random/Initialize() . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm index 652840f7e3..116082d571 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm @@ -16,7 +16,8 @@ melee_damage_lower = 10 melee_damage_upper = 10 melee_damage_type = BURN - attacktext = "slashes" + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" attack_sound = 'sound/effects/curseattack.ogg' throw_message = "passes through the smokey body of" obj_damage = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm index 2114612fce..81b541dc7b 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm @@ -21,6 +21,7 @@ layer = LARGE_MOB_LAYER sentience_type = SENTIENCE_BOSS hud_type = /datum/hud/lavaland_elite + has_field_of_vision = FALSE //You are a frikkin mini-boss var/chosen_attack = 1 var/list/attack_action_types = list() var/can_talk = FALSE diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm index 68a0e81cc7..e662f4e525 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm @@ -31,9 +31,8 @@ melee_damage_lower = 30 melee_damage_upper = 30 armour_penetration = 30 - attacktext = "beats down on" - /*attack_verb_continuous = "beats down on" - attack_verb_simple = "beat down on"*/ + attack_verb_continuous = "beats down on" + attack_verb_simple = "beat down on" attack_sound = 'sound/weapons/punch1.ogg' throw_message = "does nothing to the rocky hide of the" speed = 2 @@ -172,9 +171,8 @@ health = 30 melee_damage_lower = 5 melee_damage_upper = 5 - attacktext = "bashes against" - /*attack_verb_continuous = "bashes against" - attack_verb_simple = "bash against"*/ + attack_verb_continuous = "bashes against" + attack_verb_simple = "bash against" attack_sound = 'sound/weapons/punch1.ogg' throw_message = "does nothing to the rocky hide of the" speed = 2 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm index 884e3bb989..78b24acfb0 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm @@ -29,9 +29,8 @@ health = 800 melee_damage_lower = 20 melee_damage_upper = 20 - attacktext = "preaches to" - /*attack_verb_continuous = "preaches to" - attack_verb_simple = "preach to"*/ + attack_verb_continuous = "preaches to" + attack_verb_simple = "preach to" attack_sound = 'sound/magic/clockwork/ratvar_attack.ogg' throw_message = "doesn't affect the purity of" speed = 4 @@ -218,7 +217,7 @@ icon_state= "chronobolt" damage = 15 armour_penetration = 60 - speed = 2 + pixels_per_second = TILES_TO_PIXELS(5) eyeblur = 0 damage_type = BRUTE pass_flags = PASSTABLE diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm index c9011c5f5f..c2faa002bc 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm @@ -29,9 +29,8 @@ health = 800 melee_damage_lower = 30 melee_damage_upper = 30 - attacktext = "slashes its arms at" - /*attack_verb_continuous = "slashes its arms at" - attack_verb_simple = "slash your arms at"*/ + attack_verb_continuous = "slashes its arms at" + attack_verb_simple = "slash your arms at" attack_sound = 'sound/weapons/bladeslice.ogg' throw_message = "doesn't affect the sturdiness of" speed = 1 @@ -227,9 +226,8 @@ health = 80 melee_damage_lower = 10 melee_damage_upper = 10 - attacktext = "bites at" - /*attack_verb_continuous = "bites at" - attack_verb_simple = "bite at"*/ + attack_verb_continuous = "bites at" + attack_verb_simple = "bite at" attack_sound = 'sound/effects/curse1.ogg' throw_message = "simply misses" speed = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm index 3276965fa2..ebbf032859 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm @@ -29,9 +29,8 @@ health = 800 melee_damage_lower = 15 melee_damage_upper = 15 - attacktext = "smashes into the side of" - /*attack_verb_continuous = "smashes into the side of" - attack_verb_simple = "smash into the side of"*/ + attack_verb_continuous = "smashes into the side of" + attack_verb_simple = "smash into the side of" attack_sound = 'sound/weapons/sonic_jackhammer.ogg' throw_message = "merely dinks off of the" speed = 4 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goldgrub.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goldgrub.dm index c43e9a7461..4a3497055a 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goldgrub.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goldgrub.dm @@ -13,14 +13,16 @@ vision_range = 2 aggro_vision_range = 9 move_to_delay = 5 - friendly = "harmlessly rolls into" + friendly_verb_continuous = "harmlessly rolls into" + friendly_verb_simple = "harmlessly roll into" maxHealth = 45 health = 45 gold_core_spawnable = HOSTILE_SPAWN harm_intent_damage = 5 melee_damage_lower = 0 melee_damage_upper = 0 - attacktext = "barrels into" + attack_verb_continuous = "barrels into" + attack_verb_simple = "barrel into" attack_sound = 'sound/weapons/punch1.ogg' a_intent = INTENT_HELP speak_emote = list("screeches") diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm index 3c8cf9025f..a61f1924c8 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm @@ -14,7 +14,8 @@ move_to_delay = 10 ranged = 1 ranged_cooldown_time = 60 - friendly = "wails at" + friendly_verb_continuous = "wails at" + friendly_verb_simple = "wail at" speak_emote = list("bellows") speed = 3 maxHealth = 300 @@ -23,7 +24,8 @@ obj_damage = 100 melee_damage_lower = 18 melee_damage_upper = 18 - attacktext = "pulverizes" + attack_verb_continuous = "pulverizes" + attack_verb_simple = "pulverize" attack_sound = 'sound/weapons/punch1.ogg' throw_message = "does nothing to the rocky hide of the" vision_range = 4 @@ -35,7 +37,7 @@ var/pre_attack_icon = "Goliath_preattack" loot = list(/obj/item/stack/sheet/animalhide/goliath_hide) - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_HEAVY /mob/living/simple_animal/hostile/asteroid/goliath/Life() . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm index 39b66fbdc2..c9e650531c 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm @@ -18,10 +18,14 @@ obj_damage = 0 environment_smash = ENVIRONMENT_SMASH_NONE move_to_delay = 15 - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "squishes" - friendly = "pinches" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "squishes" + response_harm_simple = "squish" + friendly_verb_continuous = "pinches" + friendly_verb_simple = "pinch" a_intent = INTENT_HELP ventcrawler = VENTCRAWLER_ALWAYS gold_core_spawnable = FRIENDLY_SPAWN diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm index a7ce559d35..d21e39ef54 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm @@ -20,7 +20,8 @@ harm_intent_damage = 5 melee_damage_lower = 0 melee_damage_upper = 0 - attacktext = "lashes out at" + attack_verb_continuous = "lashes out at" + attack_verb_simple = "lash out at" speak_emote = list("telepathically cries") attack_sound = 'sound/weapons/pierce.ogg' throw_message = "falls right through the strange body of the" @@ -67,7 +68,8 @@ icon_gib = "syndicate_gib" mouse_opacity = MOUSE_OPACITY_OPAQUE move_to_delay = 1 - friendly = "buzzes near" + friendly_verb_continuous = "buzzes near" + friendly_verb_simple = "buzz near" vision_range = 10 speed = 3 maxHealth = 1 @@ -76,7 +78,8 @@ harm_intent_damage = 5 melee_damage_lower = 2 melee_damage_upper = 2 - attacktext = "slashes" + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" speak_emote = list("telepathically cries") attack_sound = 'sound/weapons/pierce.ogg' throw_message = "falls right through the strange body of the" @@ -107,7 +110,8 @@ obj_damage = 60 melee_damage_lower = 15 melee_damage_upper = 15 - attacktext = "lashes out at" + attack_verb_continuous = "lashes out at" + attack_verb_simple = "lash out at" speak_emote = list("echoes") attack_sound = 'sound/weapons/pierce.ogg' throw_message = "bounces harmlessly off of" @@ -173,14 +177,16 @@ icon_aggro = "legion_head" icon_dead = "legion_head" icon_gib = "syndicate_gib" - friendly = "buzzes near" + friendly_verb_continuous = "buzzes near" + friendly_verb_simple = "buzz near" vision_range = 10 maxHealth = 1 health = 5 harm_intent_damage = 5 melee_damage_lower = 12 melee_damage_upper = 12 - attacktext = "bites" + attack_verb_continuous = "bites" + attack_verb_simple = "bite" speak_emote = list("echoes") attack_sound = 'sound/weapons/pierce.ogg' throw_message = "is shrugged off by" @@ -396,8 +402,6 @@ ears = /obj/item/radio/headset gloves = /obj/item/clothing/gloves/color/fyellow id = /obj/item/card/id/silver/reaper //looks cool and has a fancy name but only a 1% chance - back = /obj/item/storage/backpack - backpack_contents = list(/obj/item/stack/cable_coil = 12, /obj/item/assembly/flash = 1, /obj/item/storage/fancy/donut_box = 1, /obj/item/storage/fancy/cigarettes/cigpack_shadyjims = 1, /obj/item/lighter = 1) if(prob(99)) id = /obj/item/card/id id_job = "Assisant" @@ -407,11 +411,14 @@ gloves = /obj/item/clothing/gloves/color/yellow if(prob(10)) back = /obj/item/twohanded/spear - backpack_contents = null + else if(prob(80)) //Now they dont always have a backpack + back = /obj/item/storage/backpack + backpack_contents = list(/obj/item/stack/cable_coil = 1, /obj/item/assembly/flash = 1, /obj/item/storage/fancy/donut_box = 1, /obj/item/storage/fancy/cigarettes/cigpack_shadyjims = 1, /obj/item/lighter = 1) if(prob(90)) r_pocket = /obj/item/kitchen/knife if(prob(60)) l_pocket = /obj/item/soap/homemade + if("Beelegion") uniform = /obj/item/clothing/under/color/yellow suit = /obj/item/clothing/suit/hooded/bee_costume diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_demon.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_demon.dm index e00ec9fe25..66241e3d75 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_demon.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_demon.dm @@ -9,7 +9,7 @@ mob_biotypes = MOB_ORGANIC|MOB_BEAST mouse_opacity = MOUSE_OPACITY_ICON speak_emote = list("telepathically cries") - speed = 2 + speed = 1 move_to_delay = 2 projectiletype = /obj/item/projectile/temp/basilisk/ice projectilesound = 'sound/weapons/pierce.ogg' @@ -23,10 +23,11 @@ obj_damage = 40 melee_damage_lower = 15 melee_damage_upper = 15 - attacktext = "slices" + attack_verb_continuous = "slices" + attack_verb_simple = "slice" attack_sound = 'sound/weapons/bladeslice.ogg' - vision_range = 9 - aggro_vision_range = 9 + vision_range = 7 + aggro_vision_range = 7 move_force = MOVE_FORCE_VERY_STRONG move_resist = MOVE_FORCE_VERY_STRONG pull_force = MOVE_FORCE_VERY_STRONG @@ -55,8 +56,9 @@ if(isclosedturf(T)) continue possible_ends |= T - var/turf/end = pick(possible_ends) - do_teleport(src, end, 0, channel=TELEPORT_CHANNEL_BLUESPACE, forced = TRUE) + if(length(possible_ends)) + var/turf/end = pick(possible_ends) + do_teleport(src, end, 0, channel=TELEPORT_CHANNEL_BLUESPACE, forced = TRUE) SLEEP_CHECK_DEATH(8) return ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_whelp.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_whelp.dm index c8d5cf4b73..b62fb4a665 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_whelp.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice_whelp.dm @@ -7,7 +7,8 @@ icon_dead = "ice_whelp_dead" mob_biotypes = MOB_ORGANIC|MOB_BEAST mouse_opacity = MOUSE_OPACITY_ICON - friendly = "stares down" + friendly_verb_continuous = "stares down" + friendly_verb_simple = "stare down" speak_emote = list("roars") speed = 30 move_to_delay = 30 @@ -19,7 +20,8 @@ armour_penetration = 20 melee_damage_lower = 20 melee_damage_upper = 20 - attacktext = "chomps" + attack_verb_continuous = "chomps" + attack_verb_simple = "chomp" attack_sound = 'sound/magic/demon_attack1.ogg' vision_range = 9 aggro_vision_range = 9 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm index 71c6d61d5d..c3e4f24c43 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm @@ -8,9 +8,8 @@ environment_smash = ENVIRONMENT_SMASH_WALLS minbodytemp = 0 maxbodytemp = INFINITY - response_help = "pokes" - response_disarm = "shoves" - response_harm = "strikes" + response_harm_continuous = "strikes" + response_harm_simple = "strike" status_flags = 0 a_intent = INTENT_HARM var/crusher_loot @@ -63,7 +62,7 @@ ..(gibbed) /mob/living/simple_animal/hostile/asteroid/proc/spawn_crusher_loot() - butcher_results[crusher_loot] = 1 + LAZYSET(butcher_results, crusher_loot, 1) /mob/living/simple_animal/hostile/asteroid/handle_temperature_damage() if(bodytemperature < minbodytemp) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm index 0576d0ecfe..ac2ce37d3f 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm @@ -7,7 +7,8 @@ icon_dead = "polarbear_dead" mob_biotypes = MOB_ORGANIC|MOB_BEAST mouse_opacity = MOUSE_OPACITY_ICON - friendly = "growls at" + friendly_verb_continuous = "growls at" + friendly_verb_simple = "growl at" speak_emote = list("growls") speed = 12 move_to_delay = 12 @@ -16,7 +17,8 @@ obj_damage = 40 melee_damage_lower = 25 melee_damage_upper = 25 - attacktext = "claws" + attack_verb_continuous = "claws" + attack_verb_simple = "claw" attack_sound = 'sound/weapons/bladeslice.ogg' vision_range = 2 // don't aggro unless you basically antagonize it, though they will kill you worse than a goliath will aggro_vision_range = 9 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/wolf.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/wolf.dm index 9f17421691..013a75be75 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/wolf.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/wolf.dm @@ -7,7 +7,8 @@ icon_dead = "whitewolf_dead" mob_biotypes = MOB_ORGANIC|MOB_BEAST mouse_opacity = MOUSE_OPACITY_ICON - friendly = "howls at" + friendly_verb_continuous = "howls at" + friendly_verb_simple = "howl at" speak_emote = list("howls") speed = 5 move_to_delay = 5 @@ -19,7 +20,8 @@ rapid_melee = 2 // every second attack dodging = TRUE dodge_prob = 50 - attacktext = "bites" + attack_verb_continuous = "bites" + attack_verb_simple = "bite" attack_sound = 'sound/weapons/bite.ogg' vision_range = 7 aggro_vision_range = 7 diff --git a/code/modules/mob/living/simple_animal/hostile/mushroom.dm b/code/modules/mob/living/simple_animal/hostile/mushroom.dm index d023cf0dd8..1b13200729 100644 --- a/code/modules/mob/living/simple_animal/hostile/mushroom.dm +++ b/code/modules/mob/living/simple_animal/hostile/mushroom.dm @@ -9,15 +9,19 @@ maxHealth = 10 health = 10 butcher_results = list(/obj/item/reagent_containers/food/snacks/hugemushroomslice = 1) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "whacks" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "whacks" + response_harm_simple = "whack" harm_intent_damage = 5 obj_damage = 0 melee_damage_lower = 1 melee_damage_upper = 1 attack_same = 2 - attacktext = "chomps" + attack_verb_continuous = "chomps" + attack_verb_simple = "chomp" attack_sound = 'sound/weapons/bite.ogg' faction = list("mushroom") environment_smash = ENVIRONMENT_SMASH_NONE diff --git a/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm b/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm index ed2a407b8e..8653c40cea 100644 --- a/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm +++ b/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm @@ -9,9 +9,6 @@ mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 12 turns_per_move = 5 - response_help = "pokes" - response_disarm = "shoves" - response_harm = "hits" speed = 0 stat_attack = UNCONSCIOUS robust_searching = 1 @@ -20,7 +17,8 @@ harm_intent_damage = 5 melee_damage_lower = 10 melee_damage_upper = 15 - attacktext = "punches" + attack_verb_continuous = "punches" + attack_verb_simple = "punch" attack_sound = 'sound/weapons/punch1.ogg' a_intent = INTENT_HARM loot = list(/obj/effect/mob_spawn/human/corpse/nanotrasensoldier) @@ -31,7 +29,7 @@ speak = list("Stop resisting!", "I AM THE LAW!", "Face the wrath of the golden bolt!", "Stop breaking the law, asshole!") search_objects = 1 - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_SHOE /mob/living/simple_animal/hostile/nanotrasen/Aggro() diff --git a/code/modules/mob/living/simple_animal/hostile/netherworld.dm b/code/modules/mob/living/simple_animal/hostile/netherworld.dm index 1c8b171738..ca5d047326 100644 --- a/code/modules/mob/living/simple_animal/hostile/netherworld.dm +++ b/code/modules/mob/living/simple_animal/hostile/netherworld.dm @@ -11,7 +11,8 @@ melee_damage_lower = 25 melee_damage_upper = 50 threat = 2 - attacktext = "slashes" + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" attack_sound = 'sound/weapons/bladeslice.ogg' faction = list("creature") speak_emote = list("screams") @@ -27,7 +28,8 @@ icon_state = "mi-go" icon_living = "mi-go" icon_dead = "mi-go-dead" - attacktext = "lacerates" + attack_verb_continuous = "lacerates" + attack_verb_simple = "lacerate" speed = -0.5 var/static/list/migo_sounds deathmessage = "wails as its form turns into a pulpy mush." @@ -63,7 +65,8 @@ maxHealth = 100 melee_damage_lower = 5 melee_damage_upper = 10 - attacktext = "punches" + attack_verb_continuous = "punches" + attack_verb_simple = "punch" deathmessage = "falls apart into a fine dust." /obj/structure/spawner/nether diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm index d8737d1edc..0544ddc676 100644 --- a/code/modules/mob/living/simple_animal/hostile/pirate.dm +++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm @@ -8,9 +8,8 @@ mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 0 turns_per_move = 5 - response_help = "pushes" - response_disarm = "shoves" - response_harm = "hits" + response_help_continuous = "pushes" + response_help_simple = "push" threat = 3 speed = 0 maxHealth = 115 @@ -19,7 +18,8 @@ harm_intent_damage = 5 melee_damage_lower = 10 melee_damage_upper = 10 - attacktext = "punches" + attack_verb_continuous = "punches" + attack_verb_simple = "punch" attack_sound = 'sound/weapons/punch1.ogg' a_intent = INTENT_HARM atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) @@ -39,11 +39,12 @@ melee_damage_lower = 30 melee_damage_upper = 30 armour_penetration = 35 - attacktext = "slashes" + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" attack_sound = 'sound/weapons/blade1.ogg' var/obj/effect/light_emitter/red_energy_sword/sord - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_SHOE /mob/living/simple_animal/hostile/pirate/melee/space name = "Space Pirate Swashbuckler" diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm index cc17759cc6..9045ccef51 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm @@ -7,9 +7,12 @@ icon_gib = "bat_dead" turns_per_move = 1 blood_volume = 250 - response_help = "brushes aside" - response_disarm = "flails at" - response_harm = "hits" + response_help_continuous = "brushes aside" + response_help_simple = "brush aside" + response_disarm_continuous = "flails at" + response_disarm_simple = "flail at" + response_harm_continuous = "hits" + response_harm_simple = "hit" mob_biotypes = MOB_ORGANIC|MOB_BEAST speak_chance = 0 maxHealth = 15 @@ -19,7 +22,8 @@ harm_intent_damage = 6 melee_damage_lower = 6 melee_damage_upper = 5 - attacktext = "bites" + attack_verb_continuous = "bites" + attack_verb_simple = "bite" butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 1) pass_flags = PASSTABLE faction = list("hostile") @@ -47,5 +51,6 @@ icon_gib = "secbat_dead" desc = "A fruit bat with a tiny little security hat who is ready to inject cuteness into any security operation." emote_see = list("is ready to law down the law.", "flaps about with an air of authority.") - response_help = "respects the authority of" + response_help_continuous = "respects the authority of" + response_help_simple = "respect the authority of" gold_core_spawnable = FRIENDLY_SPAWN diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm index c94046329b..35f2817028 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm @@ -8,8 +8,10 @@ icon_gib = "clown_gib" mob_biotypes = MOB_ORGANIC|MOB_HUMANOID turns_per_move = 5 - response_disarm = "gently pushes aside" - response_harm = "robusts" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "robusts" + response_harm_simple = "robust" speak = list("HONK", "Honk!", "Welcome to clown planet!") emote_see = list("honks", "squeaks") speak_chance = 1 @@ -30,6 +32,7 @@ minbodytemp = 270 maxbodytemp = 370 unsuitable_atmos_damage = 10 + footstep_type = FOOTSTEP_MOB_SHOE var/banana_time = 0 // If there's no time set it won't spawn. var/banana_type = /obj/item/grown/bananapeel var/attack_reagent @@ -69,8 +72,10 @@ icon_state = "lube" icon_living = "lube" turns_per_move = 1 - response_help = "dips a finger into" - response_disarm = "gently scoops and pours aside" + response_help_continuous = "dips a finger into" + response_help_simple = "dip a finger into" + response_disarm_continuous = "gently scoops and pours aside" + response_disarm_simple = "gently scoop and pour aside" emote_see = list("bubbles", "oozes") loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/particle_effect/foam) @@ -83,8 +88,10 @@ desc = "A fusion of clown and banana DNA birthed from a botany experiment gone wrong." icon_state = "banana tree" icon_living = "banana tree" - response_disarm = "peels" - response_harm = "peels" + response_disarm_continuous = "peels" + response_disarm_simple = "peel" + response_harm_continuous = "peels" + response_harm_simple = "peel" turns_per_move = 1 speak = list("HONK", "Honk!", "YA-HONK!!!") emote_see = list("honks", "bites into the banana", "plucks a banana off its head", "photosynthesizes") @@ -104,7 +111,8 @@ harm_intent_damage = 1 melee_damage_lower = 1 melee_damage_upper = 1 - attacktext = "cheers up" + attack_verb_continuous = "cheers up" + attack_verb_simple = "cheer up" loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/item/soap, /obj/item/seeds/banana/bluespace) banana_type = /obj/item/grown/bananapeel attack_reagent = /datum/reagent/consumable/laughter @@ -114,9 +122,12 @@ desc = "A being forged out of the pure essence of pranking, cursed into existence by a cruel maker." icon_state = "fleshclown" icon_living = "fleshclown" - response_help = "reluctantly pokes" - response_disarm = "sinks his hands into the spongy flesh of" - response_harm = "cleanses the world of" + response_help_continuous = "reluctantly pokes" + response_help_simple = "reluctantly poke" + response_disarm_continuous = "sinks his hands into the spongy flesh of" + response_disarm_simple = "sink your hands into the spongy flesh of" + response_harm_continuous = "cleanses the world of" + response_harm_simple = "cleanse the world of" speak = list("HONK", "Honk!", "I didn't ask for this", "I feel constant and horrible pain", "YA-HONK!!!", "this body is a merciless and unforgiving prison", "I was born out of mirthful pranking but I live in suffering") emote_see = list("honks", "sweats", "jiggles", "contemplates its existence") speak_chance = 5 @@ -126,7 +137,8 @@ health = 140 speed = -5 melee_damage_upper = 15 - attacktext = "limply slaps" + attack_verb_continuous = "limply slaps" + attack_verb_simple = "limply slap" obj_damage = 5 loot = list(/obj/item/clothing/suit/hooded/bloated_human, /obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/item/soap) @@ -137,9 +149,12 @@ icon_living = "long face" move_resist = INFINITY turns_per_move = 10 - response_help = "tries to awkwardly hug" - response_disarm = "pushes the unwieldy frame of" - response_harm = "tries to shut up" + response_help_continuous = "tries to awkwardly hug" + response_help_simple = "try to awkwardly hug" + response_disarm_continuous = "pushes the unwieldy frame of" + response_disarm_simple = "push the unwieldy frame of" + response_harm_continuous = "tries to shut up" + response_harm_simple = "try to shut up" speak = list("YA-HONK!!!") emote_see = list("honks", "squeaks") speak_chance = 60 @@ -149,7 +164,8 @@ speed = 10 harm_intent_damage = 5 melee_damage_lower = 5 - attacktext = "YA-HONKs" + attack_verb_continuous = "YA-HONKs" + attack_verb_simple = "YA-HONK" loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/item/soap) /mob/living/simple_animal/hostile/retaliate/clown/clownhulk @@ -158,9 +174,12 @@ icon_state = "honkhulk" icon_living = "honkhulk" move_resist = INFINITY - response_help = "tries desperately to appease" - response_disarm = "foolishly pushes" - response_harm = "angers" + response_help_continuous = "tries desperately to appease" + response_help_simple = "tries desperately to appease" + response_disarm_continuous = "foolishly pushes" + response_disarm_simple = "foolishly push" + response_harm_continuous = "angers" + response_harm_simple = "anger" speak = list("HONK", "Honk!", "HAUAUANK!!!", "GUUURRRRAAAHHH!!!") emote_see = list("honks", "sweats", "grunts") speak_chance = 5 @@ -171,7 +190,8 @@ harm_intent_damage = 15 melee_damage_lower = 15 melee_damage_upper = 20 - attacktext = "pummels" + attack_verb_continuous = "pummels" + attack_verb_simple = "pummel" obj_damage = 30 environment_smash = ENVIRONMENT_SMASH_WALLS loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/item/soap) @@ -181,16 +201,20 @@ desc = "A real lunkhead who somehow gets all the girls." icon_state = "chlown" icon_living = "chlown" - response_help = "submits to" - response_disarm = "tries to assert dominance over" - response_harm = "makes a weak beta attack at" + response_help_continuous = "submits to" + response_help_simple = "submit to" + response_disarm_continuous = "tries to assert dominance over" + response_disarm_simple = "try to assert dominance over" + response_harm_continuous = "makes a weak beta attack at" + response_harm_simple = "make a weak beta attack at" speak = list("HONK", "Honk!", "Bruh", "cheeaaaahhh?") emote_see = list("asserts his dominance", "emasculates everyone implicitly") maxHealth = 500 health = 500 speed = -2 armour_penetration = 20 - attacktext = "steals the girlfriend of" + attack_verb_continuous = "steals the girlfriend of" + attack_verb_simple = "steal the girlfriend of" attack_sound = 'sound/items/airhorn2.ogg' loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/effect/particle_effect/foam, /obj/item/soap) @@ -199,8 +223,10 @@ desc = "A slender wiry figure of alchemical origin." icon_state = "honkmunculus" icon_living = "honkmunculus" - response_help = "skeptically pokes" - response_disarm = "pushes the unwieldy frame of" + response_help_continuous = "skeptically pokes" + response_help_simple = "skeptically poke" + response_disarm_continuous = "pushes the unwieldy frame of" + response_disarm_simple = "push the unwieldy frame of" speak = list("honk") emote_see = list("squirms", "writhes") speak_chance = 1 @@ -210,7 +236,8 @@ harm_intent_damage = 5 melee_damage_lower = 5 melee_damage_upper = 10 - attacktext = "ferociously mauls" + attack_verb_continuous = "ferociously mauls" + attack_verb_simple = "ferociously maul" environment_smash = ENVIRONMENT_SMASH_NONE loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/effect/particle_effect/foam, /obj/item/soap) attack_reagent = /datum/reagent/peaceborg_confuse @@ -220,8 +247,10 @@ desc = "An ancient being born of arcane honking." icon_state = "destroyer" icon_living = "destroyer" - response_disarm = "bounces off of" - response_harm = "bounces off of" + response_disarm_continuous = "bounces off of" + response_disarm_simple = "bounce off of" + response_harm_continuous = "bounces off of" + response_harm_simple = "bounce off ot" speak = list("HONK!!!", "The Honkmother is merciful, so I must act out her wrath.", "parce mihi ad beatus honkmother placet mihi ut peccata committere,", "DIE!!!") maxHealth = 400 health = 400 @@ -231,7 +260,8 @@ melee_damage_upper = 40 armour_penetration = 30 stat_attack = UNCONSCIOUS - attacktext = "acts out divine vengeance on" + attack_verb_continuous = "acts out divine vengeance on" + attack_verb_simple = "act out divine vengeance on" obj_damage = 50 environment_smash = ENVIRONMENT_SMASH_RWALLS loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/effect/particle_effect/foam, /obj/item/soap) @@ -243,9 +273,12 @@ icon_living = "mutant" move_resist = INFINITY turns_per_move = 10 - response_help = "reluctantly sinks a finger into" - response_disarm = "squishes into" - response_harm = "squishes into" + response_help_continuous = "reluctantly sinks a finger into" + response_help_simple = "reluctantly sink a finger into" + response_disarm_continuous = "squishes into" + response_disarm_simple = "squish into" + response_harm_continuous = "squishes into" + response_harm_simple = "squish into" speak = list("aaaaaahhhhuuhhhuhhhaaaaa", "AAAaaauuuaaAAAaauuhhh", "huuuuuh... hhhhuuuooooonnnnkk", "HuaUAAAnKKKK") emote_see = list("squirms", "writhes", "pulsates", "froths", "oozes") speak_chance = 10 @@ -256,7 +289,8 @@ harm_intent_damage = 10 melee_damage_lower = 10 melee_damage_upper = 20 - attacktext = "awkwardly flails at" + attack_verb_continuous = "awkwardly flails at" + attack_verb_simple = "awkwardly flail at" loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/item/soap, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic/animal, /obj/effect/gibspawner/human/bodypartless, /obj/effect/gibspawner/human) /mob/living/simple_animal/hostile/retaliate/clown/mutant/blob @@ -269,6 +303,7 @@ health = 130 mob_size = MOB_SIZE_LARGE speed = 20 - attacktext = "bounces off of" + attack_verb_continuous = "bounces off of" + attack_verb_simple = "bounce off of" loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/effect/particle_effect/foam, /obj/item/soap, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic/animal, /obj/effect/gibspawner/human/bodypartless, /obj/effect/gibspawner/human) attack_reagent = /datum/reagent/toxin/mindbreaker diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm index ef51d8621b..8424a0a576 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm @@ -13,10 +13,14 @@ health = 15 melee_damage_lower = 5 melee_damage_upper = 5 - attacktext = "bites" - response_help = "pets" - response_disarm = "pokes" - response_harm = "splats" + attack_verb_continuous = "bites" + attack_verb_simple = "bite" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "pokes" + response_disarm_simple = "poke" + response_harm_continuous = "splats" + response_harm_simple = "splat" density = FALSE ventcrawler = VENTCRAWLER_ALWAYS faction = list("hostile") diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm index 48d16f63f3..2c94739180 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm @@ -7,9 +7,12 @@ mob_biotypes = MOB_SPIRIT speak_chance = 0 turns_per_move = 5 - response_help = "passes through" - response_disarm = "shoves" - response_harm = "hits" + response_help_continuous = "passes through" + response_help_simple = "pass through" + response_disarm_continuous = "shoves" + response_disarm_simple = "shove" + response_harm_continuous = "hits" + response_harm_simple = "hit" a_intent = INTENT_HARM healable = 0 speed = 0 @@ -20,7 +23,8 @@ melee_damage_upper = 15 del_on_death = 1 emote_see = list("weeps silently", "groans", "mumbles") - attacktext = "grips" + attack_verb_continuous = "grips" + attack_verb_simple = "grip" attack_sound = 'sound/hallucinations/growl1.ogg' speak_emote = list("weeps") deathmessage = "wails, disintegrating into a pile of ectoplasm!" @@ -32,6 +36,7 @@ pressure_resistance = 300 gold_core_spawnable = NO_SPAWN //too spooky for science blood_volume = 0 + has_field_of_vision = FALSE var/ghost_hair_style var/ghost_hair_color var/mutable_appearance/ghost_hair diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm index 29b0c0b701..ebeb2d28ec 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm @@ -8,9 +8,12 @@ mob_biotypes = MOB_ORGANIC|MOB_HUMANOID gender = MALE turns_per_move = 5 - response_help = "pokes" - response_disarm = "gently pushes aside" - response_harm = "punches" + response_help_continuous = "pokes" + response_help_simple = "poke" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "punches" + response_harm_simple = "punch" a_intent = INTENT_HARM maxHealth = 100 health = 100 @@ -18,13 +21,14 @@ harm_intent_damage = 8 melee_damage_lower = 10 melee_damage_upper = 10 - attacktext = "hits" + attack_verb_continuous = "hits" + attack_verb_simple = "hit" attack_sound = 'sound/weapons/punch1.ogg' obj_damage = 0 environment_smash = ENVIRONMENT_SMASH_NONE del_on_death = 0 - - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_SHOE + has_field_of_vision = FALSE //Legacy gameplay experience. Also they only have one dir visually. /mob/living/simple_animal/hostile/retaliate/nanotrasenpeace //this should be in a different file name = "Nanotrasen Private Security Officer" @@ -35,9 +39,12 @@ icon_dead = null icon_gib = "syndicate_gib" turns_per_move = 5 - response_help = "pokes" - response_disarm = "shoves" - response_harm = "hits" + response_help_continuous = "pokes" + response_help_simple = "poke" + response_disarm_continuous = "shoves" + response_disarm_simple = "shove" + response_harm_continuous = "hits" + response_harm_simple = "hit" speed = 0 stat_attack = UNCONSCIOUS robust_searching = 1 @@ -47,7 +54,8 @@ harm_intent_damage = 5 melee_damage_lower = 10 melee_damage_upper = 15 - attacktext = "punches" + attack_verb_continuous = "punches" + attack_verb_simple = "punch" attack_sound = 'sound/weapons/punch1.ogg' faction = list("nanotrasenprivate") a_intent = INTENT_HARM diff --git a/code/modules/mob/living/simple_animal/hostile/russian.dm b/code/modules/mob/living/simple_animal/hostile/russian.dm index 9c3e3e0b92..f7a46658c4 100644 --- a/code/modules/mob/living/simple_animal/hostile/russian.dm +++ b/code/modules/mob/living/simple_animal/hostile/russian.dm @@ -9,9 +9,6 @@ mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 0 turns_per_move = 5 - response_help = "pokes" - response_disarm = "shoves" - response_harm = "hits" speed = 0 threat = 1 maxHealth = 100 @@ -19,7 +16,8 @@ harm_intent_damage = 5 melee_damage_lower = 15 melee_damage_upper = 15 - attacktext = "punches" + attack_verb_continuous = "punches" + attack_verb_simple = "punch" attack_sound = 'sound/weapons/punch1.ogg' a_intent = INTENT_HARM loot = list(/obj/effect/mob_spawn/human/corpse/russian, @@ -30,7 +28,7 @@ status_flags = CANPUSH del_on_death = 1 - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_SHOE /mob/living/simple_animal/hostile/russian/ranged diff --git a/code/modules/mob/living/simple_animal/hostile/sharks.dm b/code/modules/mob/living/simple_animal/hostile/sharks.dm index 4008334a57..1263a23d26 100644 --- a/code/modules/mob/living/simple_animal/hostile/sharks.dm +++ b/code/modules/mob/living/simple_animal/hostile/sharks.dm @@ -12,9 +12,12 @@ speak_chance = 0 turns_per_move = 3 butcher_results = list(/obj/item/reagent_containers/food/snacks/carpmeat = 3) - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "hits" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "kicks" + response_harm_simple = "kick" speed = 0 threat = 1 maxHealth = 75 @@ -22,7 +25,8 @@ harm_intent_damage = 18 melee_damage_lower = 18 melee_damage_upper = 18 - attacktext = "maims" + attack_verb_continuous = "maims" + attack_verb_simple = "maim" attack_sound = 'sound/weapons/bite.ogg' gold_core_spawnable = 1 //Space shark aren't affected by cold. @@ -82,7 +86,8 @@ harm_intent_damage = 0 melee_damage_lower = 0 melee_damage_upper = 0 - attacktext = "violently hugs" + attack_verb_continuous = "violently hugs" + attack_verb_simple = "violently hug" vision_range = 0 /mob/living/simple_animal/hostile/shark/kawaii/death() diff --git a/code/modules/mob/living/simple_animal/hostile/skeleton.dm b/code/modules/mob/living/simple_animal/hostile/skeleton.dm index df71701bb7..f3138a773c 100644 --- a/code/modules/mob/living/simple_animal/hostile/skeleton.dm +++ b/code/modules/mob/living/simple_animal/hostile/skeleton.dm @@ -22,7 +22,8 @@ minbodytemp = 0 maxbodytemp = 1500 healable = 0 //they're skeletons how would bruise packs help them?? - attacktext = "slashes" + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" attack_sound = 'sound/hallucinations/growl1.ogg' atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) unsuitable_atmos_damage = 10 @@ -36,7 +37,7 @@ del_on_death = 1 loot = list(/obj/effect/decal/remains/human) - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_SHOE /mob/living/simple_animal/hostile/skeleton/eskimo name = "undead eskimo" @@ -104,7 +105,8 @@ melee_damage_lower = 15 melee_damage_upper = 20 light_color = LIGHT_COLOR_PURPLE - attacktext = "slashes" + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" attack_sound = 'sound/hallucinations/growl1.ogg' deathmessage = "collapses into a pile of bones, their suit dissolving among the plasma!" loot = list(/obj/effect/decal/remains/plasma) @@ -120,7 +122,8 @@ harm_intent_damage = 15 melee_damage_lower = 20 melee_damage_upper = 25 - attacktext = "blasts" + attack_verb_continuous = "blasts" + attack_verb_simple = "blast" attack_sound = 'sound/weapons/sonic_jackhammer.ogg' loot = list(/obj/effect/decal/remains/plasma, /obj/item/pickaxe/drill/jackhammer) diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm index 8c622c7f29..23304a2ef3 100644 --- a/code/modules/mob/living/simple_animal/hostile/statue.dm +++ b/code/modules/mob/living/simple_animal/hostile/statue.dm @@ -11,9 +11,10 @@ a_intent = INTENT_HARM mob_biotypes = MOB_HUMANOID threat = 3 - response_help = "touches" - response_disarm = "pushes" - + response_help_continuous = "touches" + response_help_simple = "touch" + response_disarm_continuous = "pushes" + response_disarm_simple = "push" speed = -1 maxHealth = 50000 health = 50000 @@ -24,7 +25,8 @@ obj_damage = 100 melee_damage_lower = 68 melee_damage_upper = 83 - attacktext = "claws" + attack_verb_continuous = "claws" + attack_verb_simple = "claw" attack_sound = 'sound/hallucinations/growl1.ogg' atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) @@ -125,14 +127,10 @@ // This loop will, at most, loop twice. for(var/atom/check in check_list) - for(var/mob/living/M in viewers(world.view + 1, check) - src) + for(var/mob/living/M in fov_viewers(world.view + 1, check) - src) if(M.client && CanAttack(M) && !M.silicon_privileges) if(!M.eye_blind) return M - for(var/obj/mecha/M in view(world.view + 1, check)) //assuming if you can see them they can see you - if(M.occupant && M.occupant.client) - if(!M.occupant.eye_blind) - return M.occupant return null // Cannot talk diff --git a/code/modules/mob/living/simple_animal/hostile/stickman.dm b/code/modules/mob/living/simple_animal/hostile/stickman.dm index 24bf5e9ea9..2edcc4021a 100644 --- a/code/modules/mob/living/simple_animal/hostile/stickman.dm +++ b/code/modules/mob/living/simple_animal/hostile/stickman.dm @@ -10,9 +10,6 @@ gender = MALE speak_chance = 0 turns_per_move = 5 - response_help = "pokes" - response_disarm = "shoves" - response_harm = "hits" speed = 0 blood_volume = 0 stat_attack = UNCONSCIOUS @@ -24,7 +21,8 @@ obj_damage = 0 melee_damage_lower = 10 melee_damage_upper = 10 - attacktext = "punches" + attack_verb_continuous = "punches" + attack_verb_simple = "punch" attack_sound = 'sound/weapons/punch1.ogg' a_intent = INTENT_HARM atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 8c4e19774d..9a362b680d 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -25,9 +25,6 @@ mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 0 turns_per_move = 5 - response_help = "pokes" - response_disarm = "shoves" - response_harm = "hits" threat = 1 speed = 0 stat_attack = UNCONSCIOUS @@ -37,7 +34,8 @@ harm_intent_damage = 5 melee_damage_lower = 10 melee_damage_upper = 10 - attacktext = "punches" + attack_verb_continuous = "punches" + attack_verb_simple = "punch" attack_sound = 'sound/weapons/punch1.ogg' a_intent = INTENT_HARM loot = list(/obj/effect/mob_spawn/human/corpse/syndicatesoldier) @@ -50,7 +48,7 @@ dodging = TRUE rapid_melee = 2 - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_SHOE ///////////////Melee//////////// @@ -82,7 +80,8 @@ icon_state = "syndicate_knife" icon_living = "syndicate_knife" loot = list(/obj/effect/gibspawner/human) - attacktext = "slashes" + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" attack_sound = 'sound/weapons/bladeslice.ogg' status_flags = 0 @@ -113,7 +112,8 @@ melee_damage_upper = 30 icon_state = "syndicate_sword" icon_living = "syndicate_sword" - attacktext = "slashes" + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" attack_sound = 'sound/weapons/blade1.ogg' armour_penetration = 35 light_color = LIGHT_COLOR_RED @@ -292,7 +292,8 @@ melee_damage_upper = 15 obj_damage = 0 environment_smash = ENVIRONMENT_SMASH_NONE - attacktext = "cuts" + attack_verb_continuous = "cuts" + attack_verb_simple = "cut" attack_sound = 'sound/weapons/bladeslice.ogg' faction = list(ROLE_SYNDICATE) atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm index bc932666f6..3aa3c9e566 100644 --- a/code/modules/mob/living/simple_animal/hostile/tree.dm +++ b/code/modules/mob/living/simple_animal/hostile/tree.dm @@ -10,9 +10,12 @@ threat = 1 speak_chance = 0 turns_per_move = 5 - response_help = "brushes" - response_disarm = "pushes" - response_harm = "hits" + response_help_continuous = "brushes" + response_help_simple = "brush" + response_disarm_continuous = "pushes" + response_disarm_simple = "push" + response_harm_continuous = "hits" + response_harm_simple = "hit" speed = 1 maxHealth = 250 health = 250 @@ -23,7 +26,8 @@ harm_intent_damage = 5 melee_damage_lower = 8 melee_damage_upper = 12 - attacktext = "bites" + attack_verb_continuous = "bites" + attack_verb_simple = "bite" attack_sound = 'sound/weapons/bite.ogg' speak_emote = list("pines") emote_taunt = list("growls") diff --git a/code/modules/mob/living/simple_animal/hostile/wizard.dm b/code/modules/mob/living/simple_animal/hostile/wizard.dm index 15d641299d..57fb6f829d 100644 --- a/code/modules/mob/living/simple_animal/hostile/wizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/wizard.dm @@ -8,9 +8,6 @@ mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 0 turns_per_move = 3 - response_help = "pokes" - response_disarm = "shoves" - response_harm = "hits" threat = 3 speed = 0 maxHealth = 100 @@ -18,7 +15,8 @@ harm_intent_damage = 5 melee_damage_lower = 5 melee_damage_upper = 5 - attacktext = "punches" + attack_verb_continuous = "punches" + attack_verb_simple = "punch" attack_sound = 'sound/weapons/punch1.ogg' a_intent = INTENT_HARM atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) @@ -38,7 +36,7 @@ var/next_cast = 0 - do_footstep = TRUE + footstep_type = FOOTSTEP_MOB_SHOE /mob/living/simple_animal/hostile/wizard/Initialize() . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm b/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm index 8878f17893..5c881a7b0d 100644 --- a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm +++ b/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm @@ -12,7 +12,8 @@ mouse_opacity = MOUSE_OPACITY_ICON move_to_delay = 5 threat = 1 - friendly = "floats near" + friendly_verb_continuous = "floats near" + friendly_verb_simple = "float near" speak_emote = list("puffs") vision_range = 5 speed = 0 @@ -23,7 +24,8 @@ obj_damage = 0 melee_damage_lower = 0 melee_damage_upper = 0 - attacktext = "chomps" + attack_verb_continuous = "chomps" + attack_verb_simple = "chomp" attack_sound = 'sound/weapons/punch1.ogg' throw_message = "is avoided by the" vision_range = 5 diff --git a/code/modules/mob/living/simple_animal/hostile/zombie.dm b/code/modules/mob/living/simple_animal/hostile/zombie.dm index 503f5c121e..6e4cbac022 100644 --- a/code/modules/mob/living/simple_animal/hostile/zombie.dm +++ b/code/modules/mob/living/simple_animal/hostile/zombie.dm @@ -13,7 +13,8 @@ harm_intent_damage = 5 melee_damage_lower = 21 melee_damage_upper = 21 - attacktext = "bites" + attack_verb_continuous = "bites" + attack_verb_simple = "bite" attack_sound = 'sound/hallucinations/growl1.ogg' a_intent = INTENT_HARM atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) @@ -73,7 +74,8 @@ harm_intent_damage = 5 melee_damage_lower = 21 melee_damage_upper = 21 - attacktext = "bites" + attack_verb_continuous = "bites" + attack_verb_simple = "bite" attack_sound = 'sound/hallucinations/growl1.ogg' a_intent = INTENT_HARM atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 9ad9a121ca..e8d6411c01 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -50,13 +50,18 @@ melee_damage_upper = 10 melee_damage_lower = 5 - response_help = "pets" - response_disarm = "gently moves aside" - response_harm = "swats" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently moves aside" + response_disarm_simple = "gently move aside" + response_harm_continuous = "swats" + response_harm_simple = "swat" stop_automated_movement = 1 a_intent = INTENT_HARM //parrots now start "aggressive" since only player parrots will nuzzle. - attacktext = "chomps" - friendly = "grooms" + attack_verb_continuous = "chomps" + attack_verb_simple = "chomp" + friendly_verb_continuous = "grooms" + friendly_verb_simple = "groom" mob_size = MOB_SIZE_SMALL movement_type = FLYING gold_core_spawnable = FRIENDLY_SPAWN @@ -575,7 +580,12 @@ parrot_state = PARROT_WANDER return - attacktext = pick("claws at", "chomps") + if(prob(50)) + attack_verb_continuous = "claws at" + attack_verb_simple = "claw_at" + else + attack_verb_continuous = "chomps" + attack_verb_simple = "chomp" L.attack_animal(src)//Time for the hurt to begin! //Otherwise, fly towards the mob! else diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm index 6aa7f8b401..75182b85e5 100644 --- a/code/modules/mob/living/simple_animal/shade.dm +++ b/code/modules/mob/living/simple_animal/shade.dm @@ -13,13 +13,17 @@ healable = 0 speak_emote = list("hisses") emote_hear = list("wails.","screeches.") - response_help = "puts their hand through" - response_disarm = "flails at" - response_harm = "punches" + response_help_continuous = "puts their hand through" + response_help_simple = "put your hand through" + response_disarm_continuous = "flails at" + response_disarm_simple = "flail at" + response_harm_continuous = "punches" + response_harm_simple = "punch" speak_chance = 1 melee_damage_lower = 5 melee_damage_upper = 12 - attacktext = "metaphysically strikes" + attack_verb_continuous = "metaphysically strikes" + attack_verb_simple = "metaphysically strike" minbodytemp = 0 maxbodytemp = INFINITY atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) @@ -32,6 +36,7 @@ del_on_death = TRUE initial_language_holder = /datum/language_holder/construct blood_volume = 0 + has_field_of_vision = FALSE //we are a spoopy ghost /mob/living/simple_animal/shade/death() deathmessage = "lets out a contented sigh as [p_their()] form unwinds." diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index def6327461..3491fd2f95 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -4,95 +4,141 @@ health = 20 maxHealth = 20 gender = PLURAL //placeholder - blood_volume = 550 //How much blud it has for bloodsucking + ///How much blud it has for bloodsucking + blood_volume = 550 status_flags = CANPUSH var/icon_living = "" - var/icon_dead = "" //icon when the animal is dead. Don't use animated icons for this. - var/icon_gib = null //We only try to show a gibbing animation if this exists. + ///icon when the animal is dead. Don't use animated icons for this. + var/icon_dead = "" + ///We only try to show a gibbing animation if this exists. + var/icon_gib = null var/list/speak = list() - var/list/speak_emote = list()// Emotes while speaking IE: Ian [emote], [text] -- Ian barks, "WOOF!". Spoken text is generated from the speak variable. + ///Emotes while speaking IE: Ian [emote], [text] -- Ian barks, "WOOF!". Spoken text is generated from the speak variable. + var/list/speak_emote = list() var/speak_chance = 0 - var/list/emote_hear = list() //Hearable emotes - var/list/emote_see = list() //Unlike speak_emote, the list of things in this variable only show by themselves with no spoken text. IE: Ian barks, Ian yaps + ///Hearable emotes + var/list/emote_hear = list() + ///Unlike speak_emote, the list of things in this variable only show by themselves with no spoken text. IE: Ian barks, Ian yaps. + var/list/emote_see = list() var/turns_per_move = 1 var/turns_since_move = 0 - var/stop_automated_movement = 0 //Use this to temporarely stop random movement or to if you write special movement code for animals. - var/wander = 1 // Does the mob wander around when idle? - var/stop_automated_movement_when_pulled = 1 //When set to 1 this stops the animal from moving when someone is pulling it. + ///Use this to temporarely stop random movement or to if you write special movement code for animals. + var/stop_automated_movement = 0 + ///Does the mob wander around when idle? + var/wander = 1 + ///When set to 1 this stops the animal from moving when someone is pulling it. + var/stop_automated_movement_when_pulled = 1 - //Interaction - var/response_help = "pokes" - var/response_disarm = "shoves" - var/response_harm = "hits" + ///When someone interacts with the simple animal. + ///Help-intent verb in present continuous tense. + var/response_help_continuous = "pokes" + ///Help-intent verb in present simple tense. + var/response_help_simple = "poke" + ///Disarm-intent verb in present continuous tense. + var/response_disarm_continuous = "shoves" + ///Disarm-intent verb in present simple tense. + var/response_disarm_simple = "shove" + ///Harm-intent verb in present continuous tense. + var/response_harm_continuous = "hits" + ///Harm-intent verb in present simple tense. + var/response_harm_simple = "hit" var/harm_intent_damage = 3 - var/force_threshold = 0 //Minimum force required to deal any damage + ///Minimum force required to deal any damage. + var/force_threshold = 0 - //Temperature effect + ///Temperature effect. var/minbodytemp = 250 var/maxbodytemp = 350 - //Healable by medical stacks? Defaults to yes. + ///Healable by medical stacks? Defaults to yes. var/healable = 1 - //Atmos effect - Yes, you can make creatures that require plasma or co2 to survive. N2O is a trace gas and handled separately, hence why it isn't here. It'd be hard to add it. Hard and me don't mix (Yes, yes make all the dick jokes you want with that.) - Errorage + ///Atmos effect - Yes, you can make creatures that require plasma or co2 to survive. N2O is a trace gas and handled separately, hence why it isn't here. It'd be hard to add it. Hard and me don't mix (Yes, yes make all the dick jokes you want with that.) - Errorage var/list/atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) //Leaving something at 0 means it's off - has no maximum - var/unsuitable_atmos_damage = 2 //This damage is taken when atmos doesn't fit all the requirements above + ///This damage is taken when atmos doesn't fit all the requirements above. + var/unsuitable_atmos_damage = 2 - //LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly + ///LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly. var/melee_damage_lower = 0 var/melee_damage_upper = 0 - var/obj_damage = 0 //how much damage this simple animal does to objects, if any - var/armour_penetration = 0 //How much armour they ignore, as a flat reduction from the targets armour value - var/melee_damage_type = BRUTE //Damage type of a simple mob's melee attack, should it do damage. - var/list/damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) // 1 for full damage , 0 for none , -1 for 1:1 heal from that source - var/attacktext = "attacks" + ///How much damage this simple animal does to objects, if any. + var/obj_damage = 0 + ///How much armour they ignore, as a flat reduction from the targets armour value. + var/armour_penetration = 0 + ///Damage type of a simple mob's melee attack, should it do damage. + var/melee_damage_type = BRUTE + /// 1 for full damage , 0 for none , -1 for 1:1 heal from that source. + var/list/damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) + ///Attacking verb in present continuous tense. + var/attack_verb_continuous = "attacks" + ///Attacking verb in present simple tense. + var/attack_verb_simple = "attack" var/attack_sound = null - var/friendly = "nuzzles" //If the mob does no damage with it's attack - var/environment_smash = ENVIRONMENT_SMASH_NONE //Set to 1 to allow breaking of crates,lockers,racks,tables; 2 for walls; 3 for Rwalls + ///Attacking, but without damage, verb in present continuous tense. + var/friendly_verb_continuous = "nuzzles" + ///Attacking, but without damage, verb in present simple tense. + var/friendly_verb_simple = "nuzzle" + ///Set to 1 to allow breaking of crates,lockers,racks,tables; 2 for walls; 3 for Rwalls. + var/environment_smash = ENVIRONMENT_SMASH_NONE - var/speed = 1 //LETS SEE IF I CAN SET SPEEDS FOR SIMPLE MOBS WITHOUT DESTROYING EVERYTHING. Higher speed is slower, negative speed is faster + ///LETS SEE IF I CAN SET SPEEDS FOR SIMPLE MOBS WITHOUT DESTROYING EVERYTHING. Higher speed is slower, negative speed is faster. + var/speed = 1 - //Hot simple_animal baby making vars + ///Hot simple_animal baby making vars. var/list/childtype = null var/next_scan_time = 0 - var/animal_species //Sorry, no spider+corgi buttbabies. + ///Sorry, no spider+corgi buttbabies. + var/animal_species - //simple_animal access - var/obj/item/card/id/access_card = null //innate access uses an internal ID card - var/buffed = 0 //In the event that you want to have a buffing effect on the mob, but don't want it to stack with other effects, any outside force that applies a buff to a simple mob should at least set this to 1, so we have something to check against - var/gold_core_spawnable = NO_SPAWN //If the mob can be spawned with a gold slime core. HOSTILE_SPAWN are spawned with plasma, FRIENDLY_SPAWN are spawned with blood + ///Innate access uses an internal ID card. + var/obj/item/card/id/access_card = null + ///In the event that you want to have a buffing effect on the mob, but don't want it to stack with other effects, any outside force that applies a buff to a simple mob should at least set this to TRUE, so we have something to check against. + var/buffed = FALSE + ///If the mob can be spawned with a gold slime core. HOSTILE_SPAWN are spawned with plasma, FRIENDLY_SPAWN are spawned with blood. + var/gold_core_spawnable = NO_SPAWN var/datum/component/spawner/nest - var/sentience_type = SENTIENCE_ORGANIC // Sentience type, for slime potions + ///Sentience type, for slime potions. + var/sentience_type = SENTIENCE_ORGANIC - var/list/loot = list() //list of things spawned at mob's loc when it dies - var/del_on_death = 0 //causes mob to be deleted on death, useful for mobs that spawn lootable corpses + ///list of things spawned at mob's loc when it dies. + var/list/loot = list() + ///causes mob to be deleted on death, useful for mobs that spawn lootable corpses. + var/del_on_death = FALSE var/deathmessage = "" - var/death_sound = null //The sound played on death + ///The sound played on death. + var/death_sound = null var/allow_movement_on_non_turfs = FALSE - var/attacked_sound = "punch" //Played when someone punches the creature + ///Played when someone punches the creature. + var/attacked_sound = "punch" - var/dextrous = FALSE //If the creature has, and can use, hands + ///If the creature has, and can use, hands. + var/dextrous = FALSE var/dextrous_hud_type = /datum/hud/dextrous - var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever), AI_Z_OFF (Temporarily off due to nonpresence of players) - var/can_have_ai = TRUE //once we have become sentient, we can never go back + ///The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever), AI_Z_OFF (Temporarily off due to nonpresence of players). + var/AIStatus = AI_ON + ///once we have become sentient, we can never go back. + var/can_have_ai = TRUE - var/shouldwakeup = FALSE //convenience var for forcibly waking up an idling AI on next check. + ///convenience var for forcibly waking up an idling AI on next check. + var/shouldwakeup = FALSE - //domestication + ///Domestication. var/tame = 0 - var/my_z // I don't want to confuse this with client registered_z + ///I don't want to confuse this with client registered_z. + var/my_z - var/do_footstep = FALSE + ///What kind of footstep this mob should have. Null if it shouldn't have any. + var/footstep_type /mob/living/simple_animal/Initialize() . = ..() @@ -106,6 +152,8 @@ update_simplemob_varspeed() if(dextrous) AddComponent(/datum/component/personal_crafting) + if(footstep_type) + AddComponent(/datum/component/footstep, footstep_type) /mob/living/simple_animal/Destroy() GLOB.simple_animals[AIStatus] -= src @@ -122,10 +170,6 @@ return ..() -/mob/living/simple_animal/initialize_footstep() - if(do_footstep) - ..() - /mob/living/simple_animal/updatehealth() ..() health = clamp(health, 0, maxHealth) diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm index 4b89d96e64..6e8c79c3d0 100644 --- a/code/modules/mob/living/simple_animal/slime/life.dm +++ b/code/modules/mob/living/simple_animal/slime/life.dm @@ -232,7 +232,7 @@ Feedstop(0, 0) return - add_nutrition((rand(7, 15) * CONFIG_GET(number/damage_multiplier))) + adjust_nutrition((rand(7, 15) * CONFIG_GET(number/damage_multiplier)), get_max_nutrition(), TRUE) //Heal yourself. adjustBruteLoss(-3) @@ -244,15 +244,13 @@ return if(prob(15)) - nutrition -= 1 + is_adult + adjust_nutrition(-1 - is_adult) - if(nutrition <= 0) - nutrition = 0 - if(prob(75)) - adjustBruteLoss(rand(0,5)) + if(nutrition <= 0 && prob(75)) + adjustBruteLoss(rand(0,5)) else if (nutrition >= get_grow_nutrition() && amount_grown < SLIME_EVOLUTION_THRESHOLD) - nutrition -= 20 + adjust_nutrition(-20) amount_grown++ update_action_buttons_icon() @@ -262,8 +260,10 @@ else Evolve() -/mob/living/simple_animal/slime/proc/add_nutrition(nutrition_to_add = 0) - nutrition = min((nutrition + nutrition_to_add), get_max_nutrition()) +/mob/living/simple_animal/slime/adjust_nutrition(change, max = INFINITY, slime_check = FALSE) + . = ..() + if(!slime_check) + return if(nutrition >= get_grow_nutrition()) if(powerlevel<10) if(prob(30-powerlevel*2)) diff --git a/code/modules/mob/living/simple_animal/slime/powers.dm b/code/modules/mob/living/simple_animal/slime/powers.dm index d5da6d76fc..d93993bf1f 100644 --- a/code/modules/mob/living/simple_animal/slime/powers.dm +++ b/code/modules/mob/living/simple_animal/slime/powers.dm @@ -28,7 +28,7 @@ return 0 var/list/choices = list() - for(var/mob/living/C in view(1,src)) + for(var/mob/living/C in fov_view(1,src)) if(C!=src && Adjacent(C)) choices += C @@ -184,7 +184,7 @@ var/mob/living/simple_animal/slime/M M = new(loc, child_colour) if(ckey) - M.nutrition = new_nutrition //Player slimes are more robust at spliting. Once an oversight of poor copypasta, now a feature! + M.set_nutrition(new_nutrition) //Player slimes are more robust at spliting. Once an oversight of poor copypasta, now a feature! M.powerlevel = new_powerlevel if(i != 1) step_away(M,src) diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 78f7b17616..0ef5cabc91 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -12,9 +12,12 @@ harm_intent_damage = 5 icon_living = "grey baby slime" icon_dead = "grey baby slime dead" - response_help = "pets" - response_disarm = "shoos" - response_harm = "stomps on" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "shoos" + response_disarm_simple = "shoo" + response_harm_continuous = "stomps on" + response_harm_simple = "stomp on" emote_see = list("jiggles", "bounces in place") speak_emote = list("blorbles") bubble_icon = "slime" @@ -27,6 +30,7 @@ healable = 0 gender = NEUTER blood_volume = 0 //Until someome reworks for them to have slime jelly + nutrition = 700 see_in_dark = 8 @@ -63,8 +67,6 @@ var/mutator_used = FALSE //So you can't shove a dozen mutators into a single slime var/force_stasis = FALSE - do_footstep = TRUE - var/static/regex/slime_name_regex = new("\\w+ (baby|adult) slime \\(\\d+\\)") ///////////TIME FOR SUBSPECIES @@ -102,7 +104,7 @@ create_reagents(100, NONE, NO_REAGENTS_VALUE) set_colour(new_colour) . = ..() - nutrition = 700 + AddComponent(/datum/component/footstep, FOOTSTEP_MOB_SLIME, 7.5) /mob/living/simple_animal/slime/Destroy() for (var/A in actions) @@ -267,8 +269,8 @@ return attacked += 5 if(nutrition >= 100) //steal some nutrition. negval handled in life() - nutrition -= (50 + (40 * M.is_adult)) - M.add_nutrition(50 + (40 * M.is_adult)) + adjust_nutrition(-50 - (40 * M.is_adult)) + M.adjust_nutrition(50 + (40 * M.is_adult), get_max_nutrition(), TRUE) if(health > 0) M.adjustBruteLoss(-10 + (-10 * M.is_adult)) M.updatehealth() diff --git a/code/modules/mob/living/update_icons.dm b/code/modules/mob/living/update_icons.dm index 8bf0dc98a9..f8d5d7e0ba 100644 --- a/code/modules/mob/living/update_icons.dm +++ b/code/modules/mob/living/update_icons.dm @@ -2,7 +2,6 @@ /mob/living/update_transform() var/matrix/ntransform = matrix(transform) //aka transform.Copy() var/final_pixel_y = pixel_y - var/final_dir = dir var/changed = 0 if(lying != lying_prev && rotate_on_lying) changed++ @@ -14,7 +13,7 @@ pixel_y = get_standard_pixel_y_offset() final_pixel_y = get_standard_pixel_y_offset(lying) if(dir & (EAST|WEST)) //Facing east or west - final_dir = pick(NORTH, SOUTH) //So you fall on your side rather than your face or ass + setDir(pick(NORTH, SOUTH)) //So you fall on your side rather than your face or ass if(resize != RESIZE_DEFAULT_SIZE) changed++ @@ -22,5 +21,5 @@ resize = RESIZE_DEFAULT_SIZE if(changed) - animate(src, transform = ntransform, time = 2, pixel_y = final_pixel_y, dir = final_dir, easing = EASE_IN|EASE_OUT) - setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure we restart it in next life(). + animate(src, transform = ntransform, time = 2, pixel_y = final_pixel_y, easing = EASE_IN|EASE_OUT) + floating_need_update = TRUE diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index c266bbddd3..b7546becd8 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -55,3 +55,5 @@ log_message("Client [key_name(src)] has taken ownership of mob [src]([src.type])", LOG_OWNERSHIP) SEND_SIGNAL(src, COMSIG_MOB_CLIENT_LOGIN, client) + if(has_field_of_vision && CONFIG_GET(flag/use_field_of_vision)) + LoadComponent(/datum/component/field_of_vision, field_of_vision_type) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index bd733af915..4a6da1ad56 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -35,7 +35,7 @@ continue var/datum/atom_hud/alternate_appearance/AA = v AA.onNewMob(src) - nutrition = rand(NUTRITION_LEVEL_START_MIN, NUTRITION_LEVEL_START_MAX) + set_nutrition(rand(NUTRITION_LEVEL_START_MIN, NUTRITION_LEVEL_START_MAX)) . = ..() update_config_movespeed() update_movespeed(TRUE) @@ -125,8 +125,10 @@ * * blind_message (optional) is what blind people will hear e.g. "You hear something!" * * vision_distance (optional) define how many tiles away the message can be seen. * * ignored_mobs (optional) doesn't show any message to any given mob in the list. + * * target (optional) is the other mob involved with the visible message. For example, the attacker in many combat messages. + * * target_message (optional) is what the target mob will see e.g. "[src] does something to you!" */ -/atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs) +/atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, mob/target, target_message) var/turf/T = get_turf(src) if(!T) return @@ -136,7 +138,19 @@ if(!islist(ignored_mobs)) ignored_mobs = list(ignored_mobs) hearers -= ignored_mobs - if(self_message) + + if(target_message && target && istype(target) && target.client) + hearers -= target + //This entire if/else chain could be in two lines but isn't for readibilties sake. + var/msg = target_message + if(target.see_invisibleSomething is there but you can't see it!") + return var/list/result = A.examine(src) to_chat(src, result.Join("\n")) - SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A) //same as above //note: ghosts can point, this is intended //visible_message will handle invisibility properly //overridden here and in /mob/dead/observer for different point span classes and sanity checks -/mob/verb/pointed(atom/A as mob|obj|turf in view()) +/mob/verb/pointed(atom/A as mob|obj|turf in fov_view()) set name = "Point To" set category = "Object" @@ -593,7 +619,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) stat("Failsafe Controller:", "ERROR") if(Master) stat(null) - for(var/datum/controller/subsystem/SS in Master.subsystems) + for(var/datum/controller/subsystem/SS in Master.statworthy_subsystems) SS.stat_entry() GLOB.cameranet.stat_entry() if(statpanel("Tickets")) @@ -1023,6 +1049,14 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) var/datum/language_holder/H = get_language_holder() H.open_language_menu(usr) +///Adjust the nutrition of a mob +/mob/proc/adjust_nutrition(change, max = INFINITY) //Honestly FUCK the oldcoders for putting nutrition on /mob someone else can move it up because holy hell I'd have to fix SO many typechecks + nutrition = clamp(nutrition + change, 0, max) + +///Force set the mob nutrition +/mob/proc/set_nutrition(var/change) //Seriously fuck you oldcoders. + nutrition = max(0, change) + /mob/setMovetype(newval) . = ..() update_movespeed(FALSE) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 825f015ef4..9947c8ca1e 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -12,6 +12,9 @@ vis_flags = VIS_INHERIT_PLANE //when this be added to vis_contents of something it inherit something.plane, important for visualisation of mob in openspace. + /// What receives our keyboard input. src by default. + var/datum/focus + var/lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE var/datum/mind/mind var/list/datum/action/actions = list() @@ -130,3 +133,17 @@ var/siliconaccesstoggle = FALSE var/voluntary_ghosted = FALSE //whether or not they voluntarily ghosted. + + var/has_field_of_vision = FALSE + var/field_of_vision_type = FOV_90_DEGREES + + + ///////TYPING INDICATORS/////// + /// Set to true if we want to show typing indicators. + var/typing_indicator_enabled = FALSE + /// Default icon_state of our typing indicator. Currently only supports paths (because anything else is, as of time of typing this, unnecesary. + var/typing_indicator_state = /obj/effect/overlay/typing_indicator + /// The timer that will remove our indicator for early aborts (like when an user finishes their message) + var/typing_indicator_timerid + /// Current state of our typing indicator. Used for cut overlay, DO NOT RUNTIME ASSIGN OTHER THAN FROM SHOW/CLEAR. Used to absolutely ensure we do not get stuck overlays. + var/typing_indicator_current diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 6531df5e68..2bcfd47344 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -100,7 +100,8 @@ if(mob.throwing) mob.throwing.finalize(FALSE) - if(L.pulling && !(L.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + var/atom/movable/AM = L.pulling + if(AM && AM.density && !(L.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && !ismob(AM)) L.setDir(turn(L.dir, 180)) SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOVE, src, direction, n, oldloc) diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index f348829b71..e2b3aee35d 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -1,12 +1,53 @@ //Speech verbs. -/mob/verb/say_verb(message as text) - set name = "Say" +// the _keybind verbs uses "as text" versus "as text|null" to force a popup when pressed by a keybind. +/mob/verb/say_typing_indicator() + set name = "say_indicator" + set hidden = TRUE set category = "IC" + display_typing_indicator() + var/message = input(usr, "", "say") as text|null + // If they don't type anything just drop the message. + clear_typing_indicator() // clear it immediately! + if(!length(message)) + return + return say_verb(message) + +/mob/verb/say_verb(message as text) + set name = "say" + set category = "IC" + if(!length(message)) + return if(GLOB.say_disabled) //This is here to try to identify lag problems to_chat(usr, "Speech is currently admin-disabled.") return - if(message) - say(message) + clear_typing_indicator() // clear it immediately! + say(message) + +/mob/verb/me_typing_indicator() + set name = "me_indicator" + set hidden = TRUE + set category = "IC" + display_typing_indicator() + var/message = input(usr, "", "me") as message|null + // If they don't type anything just drop the message. + clear_typing_indicator() // clear it immediately! + if(!length(message)) + return + return me_verb(message) + +/mob/verb/me_verb(message as message) + set name = "me" + set category = "IC" + if(!length(message)) + return + if(GLOB.say_disabled) //This is here to try to identify lag problems + to_chat(usr, "Speech is currently admin-disabled.") + return + + message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)) + clear_typing_indicator() // clear it immediately! + + usr.emote("me",1,message,TRUE) /mob/say_mod(input, message_mode) var/customsayverb = findtext(input, "*") @@ -16,9 +57,17 @@ else return ..() +/mob/proc/whisper_keybind() + var/message = input(src, "", "whisper") as text|null + if(!length(message)) + return + return whisper_verb(message) + /mob/verb/whisper_verb(message as text) set name = "Whisper" set category = "IC" + if(!length(message)) + return if(GLOB.say_disabled) //This is here to try to identify lag problems to_chat(usr, "Speech is currently admin-disabled.") return @@ -27,18 +76,6 @@ /mob/proc/whisper(message, datum/language/language=null) say(message, language) //only living mobs actually whisper, everything else just talks -/mob/verb/me_verb(message as message) - set name = "Me" - set category = "IC" - - if(GLOB.say_disabled) //This is here to try to identify lag problems - to_chat(usr, "Speech is currently admin-disabled.") - return - - message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)) - - usr.emote("me",1,message,TRUE) - /mob/proc/say_dead(var/message) var/name = real_name var/alt_name = "" diff --git a/code/modules/mob/say_vr.dm b/code/modules/mob/say_vr.dm index 377bb1c5fc..44dc3e2a05 100644 --- a/code/modules/mob/say_vr.dm +++ b/code/modules/mob/say_vr.dm @@ -23,7 +23,6 @@ proc/get_top_level_mob(var/mob/S) message = null mob_type_blacklist_typecache = list(/mob/living/brain) - /datum/emote/living/subtle/proc/check_invalid(mob/user, input) if(stop_bad_mime.Find(input, 1, 1)) to_chat(user, "Invalid emote.") @@ -130,6 +129,12 @@ proc/get_top_level_mob(var/mob/S) user.visible_message(message=message,self_message=message,vision_distance=1, ignored_mobs = GLOB.dead_mob_list) ///////////////// VERB CODE +/mob/living/proc/subtle_keybind() + var/message = input(src, "", "subtle") as text|null + if(!length(message)) + return + return subtle(message) + /mob/living/verb/subtle() set name = "Subtle" set category = "IC" diff --git a/code/modules/mob/status_procs.dm b/code/modules/mob/status_procs.dm index cf86e962bd..6be1afb5de 100644 --- a/code/modules/mob/status_procs.dm +++ b/code/modules/mob/status_procs.dm @@ -88,18 +88,20 @@ /mob/proc/add_eyeblur() if(!client) return - var/obj/screen/plane_master/game_world/GW = locate(/obj/screen/plane_master/game_world) in client.screen - var/obj/screen/plane_master/floor/F = locate(/obj/screen/plane_master/floor) in client.screen - GW.add_filter("blurry_eyes", 2, EYE_BLUR(clamp(eye_blurry*0.1,0.6,3))) - F.add_filter("blurry_eyes", 2, EYE_BLUR(clamp(eye_blurry*0.1,0.6,3))) + var/list/screens = list(hud_used.plane_masters["[GAME_PLANE]"], hud_used.plane_masters["[FLOOR_PLANE]"], + hud_used.plane_masters["[WALL_PLANE]"], hud_used.plane_masters["[ABOVE_WALL_PLANE]"]) + for(var/A in screens) + var/obj/screen/plane_master/P = A + P.add_filter("blurry_eyes", 2, EYE_BLUR(clamp(eye_blurry*0.1,0.6,3))) /mob/proc/remove_eyeblur() if(!client) return - var/obj/screen/plane_master/game_world/GW = locate(/obj/screen/plane_master/game_world) in client.screen - var/obj/screen/plane_master/floor/F = locate(/obj/screen/plane_master/floor) in client.screen - GW.remove_filter("blurry_eyes") - F.remove_filter("blurry_eyes") + var/list/screens = list(hud_used.plane_masters["[GAME_PLANE]"], hud_used.plane_masters["[FLOOR_PLANE]"], + hud_used.plane_masters["[WALL_PLANE]"], hud_used.plane_masters["[ABOVE_WALL_PLANE]"]) + for(var/A in screens) + var/obj/screen/plane_master/P = A + P.remove_filter("blurry_eyes") ///Adjust the drugginess of a mob /mob/proc/adjust_drugginess(amount) diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 42aaa110c8..56ec5bb816 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -425,6 +425,7 @@ mind.transfer_to(new_xeno) else transfer_ckey(new_xeno) + update_atom_languages() to_chat(new_xeno, "You are now an alien.") . = new_xeno @@ -449,7 +450,7 @@ var/list/babies = list() for(var/i=1,i<=number,i++) var/mob/living/simple_animal/slime/M = new/mob/living/simple_animal/slime(loc) - M.nutrition = round(nutrition/number) + M.set_nutrition(round(nutrition/number)) step_away(M,src) babies += M new_slime = pick(babies) diff --git a/code/modules/mob/typing_indicator.dm b/code/modules/mob/typing_indicator.dm new file mode 100644 index 0000000000..f28cbe4385 --- /dev/null +++ b/code/modules/mob/typing_indicator.dm @@ -0,0 +1,47 @@ +/// state = overlay/image/object/type/whatever add_overlay will accept +GLOBAL_LIST_EMPTY(typing_indicator_overlays) + +/// Fetches the typing indicator we'll use from GLOB.typing_indicator_overlays +/mob/proc/get_indicator_overlay(state) + . = GLOB.typing_indicator_overlays[state] + if(.) + return + // doesn't exist, make it and cache it + if(ispath(state)) + . = GLOB.typing_indicator_overlays[state] = state + // We only support paths for now because anything else isn't necessary yet. + +/// Gets the state we will use for typing indicators. Defaults to src.typing_indicator_state +/mob/proc/get_typing_indicator_icon_state() + return typing_indicator_state + +/** + * Displays typing indicator. + * @param timeout_override - Sets how long until this will disappear on its own without the user finishing their message or logging out. Defaults to src.typing_indicator_timeout + * @param state_override - Sets the state that we will fetch. Defaults to src.get_typing_indicator_icon_state() + * @param force - shows even if src.typing_indcator_enabled is FALSE. + */ +/mob/proc/display_typing_indicator(timeout_override = TYPING_INDICATOR_TIMEOUT, state_override = get_typing_indicator_icon_state(), force = FALSE) + if((!typing_indicator_enabled && !force) || typing_indicator_current) + return + typing_indicator_current = state_override + add_overlay(state_override) + typing_indicator_timerid = addtimer(CALLBACK(src, .proc/clear_typing_indicator), timeout_override, TIMER_STOPPABLE) + +/** + * Removes typing indicator. + */ +/mob/proc/clear_typing_indicator() + cut_overlay(typing_indicator_current) + typing_indicator_current = null + if(typing_indicator_timerid) + deltimer(typing_indicator_timerid) + typing_indicator_timerid = null + +/// Default typing indicator +/obj/effect/overlay/typing_indicator + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + icon = 'icons/mob/talk.dmi' + icon_state = "normal_typing" + appearance_flags = RESET_COLOR | TILE_BOUND | PIXEL_SCALE + layer = ABOVE_FLY_LAYER diff --git a/code/modules/modular_computers/hardware/_hardware.dm b/code/modules/modular_computers/hardware/_hardware.dm index 744db1572f..37f3fc434e 100644 --- a/code/modules/modular_computers/hardware/_hardware.dm +++ b/code/modules/modular_computers/hardware/_hardware.dm @@ -41,11 +41,10 @@ // Cable coil. Works as repair method, but will probably require multiple applications and more cable. if(istype(I, /obj/item/stack/cable_coil)) - var/obj/item/stack/S = I if(obj_integrity == max_integrity) to_chat(user, "\The [src] doesn't seem to require repairs.") return 1 - if(S.use(1)) + if(I.use_tool(src, user, 0, 1)) to_chat(user, "You patch up \the [src] with a bit of \the [I].") obj_integrity = min(obj_integrity + 10, max_integrity) return 1 diff --git a/code/modules/modular_computers/hardware/hard_drive.dm b/code/modules/modular_computers/hardware/hard_drive.dm index 285463bc0f..76463c6867 100644 --- a/code/modules/modular_computers/hardware/hard_drive.dm +++ b/code/modules/modular_computers/hardware/hard_drive.dm @@ -157,6 +157,7 @@ max_capacity = 64 icon_state = "ssd_mini" w_class = WEIGHT_CLASS_TINY + custom_price = 150 /obj/item/computer_hardware/hard_drive/small/syndicate // Syndicate variant - very slight better desc = "An efficient SSD for portable devices developed by a rival organisation." diff --git a/code/modules/modular_computers/laptop_vendor.dm b/code/modules/modular_computers/laptop_vendor.dm index 2bed456c41..9e0e1c8014 100644 --- a/code/modules/modular_computers/laptop_vendor.dm +++ b/code/modules/modular_computers/laptop_vendor.dm @@ -244,12 +244,12 @@ visible_message("[user] inserts [c.value] credits into [src].") qdel(c) return - /*else if(istype(I, /obj/item/holochip)) + else if(istype(I, /obj/item/holochip)) var/obj/item/holochip/HC = I credits += HC.credits - visible_message("[user] inserts a $[HC.credits] holocredit chip into [src].") + visible_message("[user] inserts a [HC.credits] cr holocredit chip into [src].") qdel(HC) - return + return else if(istype(I, /obj/item/card/id)) if(state != 2) return @@ -260,8 +260,8 @@ say("Insufficient money on card to purchase!") return credits += target_credits - say("$[target_credits] has been desposited from your account.") - return */ //Goonconomy when + say("[target_credits] cr has been desposited from your account.") + return return ..() // Simplified payment processing, returns 1 on success. diff --git a/code/modules/movespeed/modifiers/mobs.dm b/code/modules/movespeed/modifiers/mobs.dm index d468c133a6..a2176ca95e 100644 --- a/code/modules/movespeed/modifiers/mobs.dm +++ b/code/modules/movespeed/modifiers/mobs.dm @@ -24,7 +24,8 @@ variable = TRUE /datum/movespeed_modifier/damage_slowdown_flying - movetypes = FLOATING + movetypes = FLYING + blacklisted_movetypes = FLOATING variable = TRUE /datum/movespeed_modifier/equipment_speedmod diff --git a/code/modules/newscaster/newscaster_machine.dm b/code/modules/newscaster/newscaster_machine.dm index 95a24817a0..cb2d49fc64 100644 --- a/code/modules/newscaster/newscaster_machine.dm +++ b/code/modules/newscaster/newscaster_machine.dm @@ -12,6 +12,7 @@ GLOBAL_LIST_EMPTY(allCasters) desc = "A standard Nanotrasen-licensed newsfeed handler for use in commercial space stations. All the news you absolutely have no use for, in one place!" icon = 'icons/obj/terminals.dmi' icon_state = "newscaster_normal" + plane = ABOVE_WALL_PLANE verb_say = "beeps" verb_ask = "beeps" verb_exclaim = "beeps" diff --git a/code/modules/paperwork/paper_premade.dm b/code/modules/paperwork/paper_premade.dm index 2d03a17e0a..23c8d47323 100644 --- a/code/modules/paperwork/paper_premade.dm +++ b/code/modules/paperwork/paper_premade.dm @@ -54,7 +54,7 @@ /obj/item/paper/guides/cogstation/job_changes name = "MEMO: Job Changes" - info = "To ensure minimal employee downtime, please take note of the following changes to select professions that Cogstation specifically requires:
\n
\n- Chemists are to have basic Research accessand an encryption key for the Science channel.
\n- Roboticists are to have basic Medical and Morgue access.
\n- Engineers and Atmospheric Technicians are to have Warehouse and Mining access.
\n- The Cook should not have Morgue access
\n- The Clown and Mime are to have Maintenance access. This is necessary due to the location of their offices.
\n
\nGenerated by Organic Resources Bot #2053" + info = "To ensure minimal employee downtime, please take note of the following changes to select professions that CogStation specifically requires:
\n
\n- Scientists are to have access to chemistry in order to reach the MedSci router.
\n
\n- Chemists should at the very least be provided with an encryption key for the Science channel, if not basic access to the Research department at large.
\n- Roboticists are to have basic Medical and Morgue access.
\n- Engineers and Atmospheric Technicians are to have Warehouse and Mining access.
\n- The Cook should not have Morgue access
\n- The Clown and Mime are to have Maintenance access. This is necessary due to the location of their offices.
\n
\nGenerated by Organic Resources Bot #2053" /obj/item/paper/guides/cogstation/letter_sec name = "To future Security personnel" @@ -86,7 +86,11 @@ /obj/item/paper/guides/cogstation/letter_eng name = "To future Engineering staff:" - info = "I'm not gonna sugarcoat this. Compared to other departments, you might have your work cut out for you. CogStation is an entirely different beast than your standard Box, but everyone's still gonna expect you to keep the place running.
\n
\n If there's any good news, it's your time to shine if you know how to run a thermo-electric generator. That's what this station runs on, and CentCom isn't planning on changing that. If it's absolutely critical you might be able to run a singularity or tesla engine east of mining, but it won't have any sort of shielding out there.
\n
\nThe air system's different too. It's multiple small networks instead of a single big one, with air hookups across the station. Fortunately it's not that complicated, but it comes at the expense of being able to filter out and reuse specific gases. Besides, you'll probably be busy enough with the engine and general upkeep anyway.
\n
\nThe disposal network in contrast is significantly more complicated, yet more capable. I've already elaborated on it, so I'll let you find and read my write-up for that. As for the routing system, it's just begging to get hit by a stray meteor so consider other utilities a higher priority.
\n
\nGood luck. You're gonna need it.
\n
\n-C. Donnelly
Architectural Analyst" + info = "I'm not gonna sugarcoat this. Compared to other departments, you might have your work cut out for you. CogStation is an entirely different beast than your standard Box, but everyone's still gonna expect you to keep the place running.
\n
\n If there's any good news, it's your time to shine if you know how to run a thermo-electric generator. That's what this station runs on, and that isn't likely to change anytime soon. If it's absolutely critical you might be able to run a singularity or tesla engine east of mining, but it won't have any sort of shielding out there.
\n
\nYou still have three solar arrays to work with, two of them being on each end of the starboard side. The port side array will need you to either get access from a head of staff or security, unless you want to spacewalk around the whole station. Don't be afraid to ask the latter - they're there for you, after all. As for other utilities the air system is a bit different than you'd expect, but fortunately you should have the atmos techs this station needed a long time ago. The disposal network is significantly more complicated, yet more capable. I've already elaborated on it, so I'll let you find and read my write-up for that. As for the routing system, it's just begging to get hit by a stray meteor so consider other utilities a higher priority.
\n
\nGood luck. You're gonna need it.
\n
\n-C. Donnelly
Architectural Analyst" + +/obj/item/paper/guides/cogstation/letter_atmos + name = "To future Atmospheric Technicians:" + info = "If the place that this station used to call home still hired atmos techs, odds are we could've gotten this place up and running a lot sooner. Alas, the past is in the past and the hard work's already been done. You still have a job to do, but it shouldn't be much different from other stations in this sector. That being said, be aware of the following:
\n
\n - If you haven't already noticed, the atmospherics department is separate from the rest of the station. You'll either need to spacewalk or take a transit tube to reach it, but it still connects to the station's air system at large.
\n
\n- Seeing as the TEG already uses the standard red and blue for it's heating/cooling loops, the scrubber pipes are ORANGE. The main air supply pipes are a purpleish-blue - HOWEVER, these aren't the only air pipes you'll see. We've decided to reuse existing lines from the old air hookup system - these pipes are CYAN and serve to supply air to specific areas. There's also a VIOLET line to help keep the TEG stable.
\n
\nNanotrasen's invested a considerable amount into updating this system, so even if Murphy's Law is alive and well in this sector, the air system isn't one of the things that should fail. If a section of the station is having air problems, check the old air hookups FIRST. Your problem could be as simple as a 'greytider' turning a valve or a clown hooking up a laughing gas canister.
\n
\n-C. Donnelly
Architectural Analyst" /obj/item/paper/guides/cogstation/letter_chief name = "To the future Chief Engineer:" @@ -112,6 +116,10 @@ name = "To the future Research Director" info = "Apologies if you were expecting a letter from the station's Research Director, but just prior to translocation we found out they were a BLF operative. I wouldn't trust a single word they wrote and while I'm not a scientist, something tells me your department will have the easiest time adjusting to this station.
\n
\nYou should have everything you need - this is a research facility after all. It's just a matter of finding it, which shouldn't be too hard. Folks like you are why we're out in deep space, after all!
\n-Louis Cannon
\nFormer Head of Security" +/obj/item/paper/fluff/cogstation/letter_arrd + name = "To the future Research Director" + info = "Listen, I doubt I need to tell you to how to do your job. From what I've heard this station is getting a state-of-the-art xenobiology lab after it gets translocated, and I don't know the first thing about what you guys do about those slimes. However, there's one thing I do know and it's that your station will have botanists.
\n
\nIt's crucial you give them everything they need, so long as they agree to maintain as many apiaries as humanely possible. I know it sounds ridiculous, but it's the ONLY way to keep the floor cluwnes at bay. If you don't know what a floor cluwne is, trust me when I say you do NOT want to find out!
\nJesse P.
\nFormer CogStation RD" + /obj/item/paper/fluff/cogstation/letter_cap name = "Captain's Log" info = "So I guess some of the other heads have decided to leave little notes for future employees here. Heartwarming, but the most important thing I figure I can leave you is the truth. Nevermind the Syndicate, the xenomorphs, the apocalyptic death cults I hear are a thing way out there - I'm convinced we are our own worst enemy.
\n
\nDon't believe me? Maybe you can ask Chief Engineer Earp. Oh right, he vaporized himself trying to produce enough power to keep the lights on in Space China for a week, despite only needing a sliver of that to run this place as intended. Or maybe you can ask Head of Security Cannon, who executed our Research Director in plain sight of everyone. Even if he was in the right, the final frontier isn't the goddamn wild west! Hell, maybe you can ask one of your 'staff assistants', although in my experience the only ones they seem to want to help is themselves.
\n
\nOf course, the REAL problems are with the higher-ups that stationed us on this deathtrap before deciding to send it your way, but there's only so much I can say and get away with it, for instance that they only sent this station since they could care less if it was a total loss. By the time you read this, I'll already be long gone. Maybe it'll be a different story with your crew, but between you and me, I wouldn't hold my breath...unless they fuck up the air system.
\n
\nDom Kahn
Former Captain of Nanotrasen CogStation" @@ -128,6 +136,18 @@ name = "Mysterious Note" info = "ThE rInGmAsTeR dOeSn'T rUn ThE cIrCus... HONK!!!" +/obj/item/paper/fluff/cogstation/secsolars + name = "A heads up:" + info = "I'm hoping you guys are aware of the access changes this station requires, but one thing they might have forgot to mention is that one of the station's solar arrays and air hookups are wedged squarely behind your department. Engineering might need to come through your department to access them.
\n
\nWhile I can imagine potential concerns, there shouldn't be any problems if both sides are transparent and communicative. The engineer is most likely there to do their job of keeping the station running, and will only need to pass through your department office and interrogation room (or alternatively, the bridge). You're free to get the doors for them and/or watch them work if it helps put your mind at ease. If they loiter or otherwise act suspiciously then you might want to have a word with them.
\n
\n-C. Donnelly
Architectural Analyst" + +/obj/item/paper/fluff/cogstation/eva + name = "MEMO: Spacesuits" + info = "As a Head of Personnel, you may be familiar with crew members requesting EVA access, particularly when there is an absence of credible threats on the station. While it is your decision to grant or deny access unless overriden by your superior(s), you should be aware of an abundance of spacesuits on this station. While intended for emergencies, these suits are cheaper to replace. You may find it beneficial to direct aspiring 'space explorers' towards finding one of these suits instead, although it is advised you order replacement suits in advance through the cargo department.
\n
\n-Generated by Organic Resources Bot #2053" + +/obj/item/paper/fluff/cogstation/chemists + name = "Re: Scientists?!" + info = "Scientists should have access to the chemistry lab. This is intentional as opposed to some sort of oversight - after all, they need to reach the medsci router somehow.
\n
\nIf anything you should see this as a blessing, as you won't need to sideline whatever it is you're doing to get them what they need. Your focus should remain on predominantly medical goods, just like other stations in this sector.
\n
\n- Dr. Halley" + /obj/item/paper/fluff/cogstation/mime name = "Au futur Mime" info = "Toutes mes excuses pour toute mauvaise grammaire, je ne suis pas un haut-parleur naturel Français et a dû utiliser NanoTranslate. Bien que vous puissiez être mécontent de l’emplacement de votre bureau, s’il vous plaît comprendre que c’était le seul endroit où nous pourrions le mettre sans problèmes de sécurité et/ou CentClown se plaindre à ce sujet. Nous nous excusons également pour l’absence d’une zone de performance dédiée, mais nous espérons que vous accorder un accès à l’entretien compensera.
\n
\n-C. Donnelly
\n
\nAnalyste Architectural" diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index ca5219375f..1c14a30a8a 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -220,3 +220,17 @@ item_state = initial(item_state) lefthand_file = initial(lefthand_file) righthand_file = initial(righthand_file) + +/obj/item/pen/survival + name = "survival pen" + desc = "The latest in portable survival technology, this pen was designed as a miniature diamond pickaxe. Watchers find them very desirable for their diamond exterior." + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "digging_pen" + item_state = "pen" + force = 3 + w_class = WEIGHT_CLASS_TINY + custom_materials = list(/datum/material/iron=10, /datum/material/diamond=100, /datum/material/titanium = 10) + pressure_resistance = 2 + grind_results = list(/datum/reagent/iron = 2, /datum/reagent/iodine = 1) + tool_behaviour = TOOL_MINING //For the classic "digging out of prison with a spoon but you're in space so this analogy doesn't work" situation. + toolspeed = 10 //You will never willingly choose to use one of these over a shovel. diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 8db531aa5e..3c4aebdba3 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -337,3 +337,15 @@ grind_results = list(/datum/reagent/iodine = 40, /datum/reagent/iron = 10) var/charges = 5 var/max_charges = 5 + +/obj/item/toner/large + name = "large toner cartridge" + grind_results = list(/datum/reagent/iodine = 90, /datum/reagent/iron = 10) + charges = 15 + max_charges = 15 + +/obj/item/toner/extreme + name = "extremely large toner cartridge" + desc = "Why would ANYONE need THIS MUCH TONER?" + charges = 200 + max_charges = 200 diff --git a/code/modules/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm index f039dc32b2..705888a427 100644 --- a/code/modules/photography/camera/camera.dm +++ b/code/modules/photography/camera/camera.dm @@ -15,6 +15,7 @@ flags_1 = CONDUCT_1 slot_flags = ITEM_SLOT_NECK custom_materials = list(/datum/material/iron = 50, /datum/material/glass = 150) + custom_price = 120 var/flash_enabled = TRUE var/state_on = "camera" var/state_off = "camera_off" diff --git a/code/modules/photography/photos/frame.dm b/code/modules/photography/photos/frame.dm index 67559c0381..11ad81ebf0 100644 --- a/code/modules/photography/photos/frame.dm +++ b/code/modules/photography/photos/frame.dm @@ -40,6 +40,7 @@ /obj/item/wallframe/picture/examine(mob/user) if(user.is_holding(src) && displayed) displayed.show(user) + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artok", /datum/mood_event/artok) return list() return ..() @@ -109,6 +110,7 @@ /obj/structure/sign/picture_frame/examine(mob/user) if(in_range(src, user) && framed) framed.show(user) + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artok", /datum/mood_event/artok) return list() return ..() diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index c2cdf1da8b..f1108189c7 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -48,7 +48,7 @@ /obj/machinery/power/apc name = "area power controller" desc = "A control terminal for the area's electrical systems." - + plane = ABOVE_WALL_PLANE icon_state = "apc0" use_power = NO_POWER_USE req_access = null @@ -597,19 +597,15 @@ user.visible_message("[user.name] adds cables to the APC frame.", \ "You start adding cables to the APC frame...") playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1) - if(do_after(user, 20, target = src)) - if (C.get_amount() < 10 || !C) + if(C.use_tool(src, user, 20, 10) && !terminal && opened && has_electronics) + var/turf/T = get_turf(src) + var/obj/structure/cable/N = T.get_cable_node() + if (prob(50) && electrocute_mob(usr, N, N, 1, TRUE)) + do_sparks(5, TRUE, src) return - if (C.get_amount() >= 10 && !terminal && opened && has_electronics) - var/turf/T = get_turf(src) - var/obj/structure/cable/N = T.get_cable_node() - if (prob(50) && electrocute_mob(usr, N, N, 1, TRUE)) - do_sparks(5, TRUE, src) - return - C.use(10) - to_chat(user, "You add cables to the APC frame.") - make_terminal() - terminal.connect_to_network() + to_chat(user, "You add cables to the APC frame.") + make_terminal() + terminal.connect_to_network() else if (istype(W, /obj/item/electronics/apc) && opened) if (has_electronics) to_chat(user, "There is already a board inside the [src]!") @@ -1583,4 +1579,5 @@ /obj/item/electronics/apc name = "power control module" icon_state = "power_mod" + custom_price = 50 desc = "Heavy-duty switching circuits for power control." diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 239b38460c..0d674a2f77 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -39,6 +39,7 @@ By design, d1 is the smallest direction and d2 is the highest icon = 'icons/obj/power_cond/cables.dmi' icon_state = "0-1" level = 1 //is underfloor + plane = ABOVE_WALL_PLANE layer = WIRE_LAYER //Above hidden pipes, GAS_PIPE_HIDDEN_LAYER anchored = TRUE obj_flags = CAN_BE_HIT | ON_BLUEPRINTS @@ -487,6 +488,7 @@ By design, d1 is the smallest direction and d2 is the highest /obj/item/stack/cable_coil name = "cable coil" + custom_price = 75 gender = NEUTER //That's a cable coil sounds better than that's some cable coils icon = 'icons/obj/power.dmi' icon_state = "coil" @@ -510,6 +512,7 @@ By design, d1 is the smallest direction and d2 is the highest full_w_class = WEIGHT_CLASS_SMALL grind_results = list(/datum/reagent/copper = 2) //2 copper per cable in the coil usesound = 'sound/items/deconstruct.ogg' + used_skills = list(/datum/skill/level/job/wiring) /obj/item/stack/cable_coil/cyborg is_cyborg = 1 @@ -591,8 +594,6 @@ By design, d1 is the smallest direction and d2 is the highest amount += extra update_icon() - - /////////////////////////////////////////////// // Cable laying procedures ////////////////////////////////////////////// diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index cc321fdb4d..c788b9b033 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -227,6 +227,7 @@ icon_state = "h+cell" maxcharge = 15000 chargerate = 2250 + rating = 2 /obj/item/stock_parts/cell/high/empty start_charged = FALSE @@ -237,6 +238,7 @@ maxcharge = 20000 custom_materials = list(/datum/material/glass=300) chargerate = 2000 + rating = 3 /obj/item/stock_parts/cell/super/empty start_charged = FALSE @@ -247,6 +249,7 @@ maxcharge = 30000 custom_materials = list(/datum/material/glass=400) chargerate = 3000 + rating = 4 /obj/item/stock_parts/cell/hyper/empty start_charged = FALSE @@ -258,6 +261,7 @@ maxcharge = 40000 custom_materials = list(/datum/material/glass=600) chargerate = 4000 + rating = 5 /obj/item/stock_parts/cell/bluespace/empty start_charged = FALSE @@ -313,7 +317,7 @@ /obj/item/stock_parts/cell/emproof/ComponentInitialize() . = ..() - AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF) + AddElement(/datum/element/empprotection, EMP_PROTECT_SELF) /obj/item/stock_parts/cell/emproof/empty start_charged = FALSE diff --git a/code/modules/power/floodlight.dm b/code/modules/power/floodlight.dm index 9fb1a1ce7d..e0b3f5f316 100644 --- a/code/modules/power/floodlight.dm +++ b/code/modules/power/floodlight.dm @@ -15,8 +15,7 @@ state = FLOODLIGHT_NEEDS_WIRES desc = "A bare metal frame looking vaguely like a floodlight. Requires wiring." else if(istype(O, /obj/item/stack/cable_coil) && (state == FLOODLIGHT_NEEDS_WIRES)) - var/obj/item/stack/S = O - if(S.use(5)) + if(O.use_tool(src, user, 0, 5)) to_chat(user, "You wire [src].") name = "wired [name]" desc = "A bare metal frame looking vaguely like a floodlight. Requires securing with a screwdriver." diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm index 582d72f6c0..1644673ece 100644 --- a/code/modules/power/gravitygenerator.dm +++ b/code/modules/power/gravitygenerator.dm @@ -39,9 +39,9 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne if(prob(20)) set_broken() -/obj/machinery/gravity_generator/tesla_act(power, tesla_flags) +/obj/machinery/gravity_generator/zap_act(power, zap_flags) ..() - if(tesla_flags & TESLA_MACHINE_EXPLOSIVE) + if(zap_flags & ZAP_MACHINE_EXPLOSIVE) qdel(src)//like the singulo, tesla deletes it. stops it from exploding over and over /obj/machinery/gravity_generator/update_icon_state() diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 7ad9f3a6ce..344d41071d 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -118,8 +118,7 @@ return if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/coil = W - if(coil.use(1)) + if(W.use_tool(src, user, 0, 1, max_level = JOB_SKILL_TRAINED)) icon_state = "[fixture_type]-construct-stage2" stage = 2 user.visible_message("[user.name] adds wires to [src].", \ @@ -193,7 +192,7 @@ var/on = FALSE // 1 if on, 0 if off var/on_gs = FALSE var/static_power_used = 0 - var/brightness = 11 // luminosity when on, also used in power calculation + var/brightness = 9 // luminosity when on, also used in power calculation var/bulb_power = 0.75 // basically the alpha of the emitted light source var/bulb_colour = "#FFF6ED" // befault colour of the light. var/status = LIGHT_OK // LIGHT_OK, _EMPTY, _BURNED or _BROKEN @@ -232,7 +231,8 @@ icon_state = "bulb" base_state = "bulb" fitting = "bulb" - brightness = 6 + brightness = 5 + nightshift_brightness = 4 bulb_colour = "#FFDDBB" desc = "A small lighting fixture." light_type = /obj/item/light/bulb @@ -274,11 +274,11 @@ spawn(2) switch(fitting) if("tube") - brightness = 11 + brightness = 9 if(prob(2)) break_light_tube(1) if("bulb") - brightness = 6 + brightness = 5 if(prob(5)) break_light_tube(1) spawn(1) @@ -314,7 +314,7 @@ . = ..() SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) if(on && status == LIGHT_OK) - SSvis_overlays.add_vis_overlay(src, overlayicon, base_state, EMISSIVE_LAYER, EMISSIVE_PLANE, dir, clamp(light_power*250, 30, 200)) + SSvis_overlays.add_vis_overlay(src, overlayicon, base_state, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE, dir, clamp(light_power*250, 30, 200)) // update the icon_state and luminosity of the light depending on its state @@ -361,11 +361,11 @@ set_light(0) update_icon() - active_power_usage = (brightness * 7.2) + active_power_usage = (brightness * 10) if(on != on_gs) on_gs = on if(on) - static_power_used = brightness * 14.4 * (hijacked ? 2 : 1) //20W per unit luminosity + static_power_used = brightness * 20 * (hijacked ? 2 : 1) //20W per unit luminosity addStaticPower(static_power_used, STATIC_LIGHT) else removeStaticPower(static_power_used, STATIC_LIGHT) @@ -687,9 +687,9 @@ on = TRUE update() -/obj/machinery/light/tesla_act(power, tesla_flags) - if(tesla_flags & TESLA_MACHINE_EXPLOSIVE) - explosion(src,0,0,0,flame_range = 5, adminlog = 0) +/obj/machinery/light/zap_act(power, zap_flags) + if(zap_flags & ZAP_MACHINE_EXPLOSIVE) + explosion(src,0,0,0,flame_range = 5, adminlog = FALSE) qdel(src) else return ..() @@ -748,7 +748,7 @@ icon_state = "ltube" base_state = "ltube" item_state = "c_tube" - brightness = 11 + brightness = 9 /obj/item/light/tube/broken status = LIGHT_BROKEN @@ -761,7 +761,7 @@ item_state = "contvapour" lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' - brightness = 6 + brightness = 5 /obj/item/light/bulb/broken status = LIGHT_BROKEN @@ -830,7 +830,8 @@ icon = 'icons/obj/lighting.dmi' base_state = "floor" // base description and icon_state icon_state = "floor" - brightness = 6 + brightness = 5 + nightshift_brightness = 4 layer = 2.5 light_type = /obj/item/light/bulb fitting = "bulb" diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 4cec49945a..f84b639d68 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -310,6 +310,7 @@ if(H.gloves) var/obj/item/clothing/gloves/G = H.gloves if(G.siemens_coefficient == 0) + SEND_SIGNAL(M, COMSIG_LIVING_SHOCK_PREVENTED, power_source, source, siemens_coeff, dist_check) return 0 //to avoid spamming with insulated glvoes on var/area/source_area diff --git a/code/modules/power/rtg.dm b/code/modules/power/rtg.dm index afbeef30a1..b558031fab 100644 --- a/code/modules/power/rtg.dm +++ b/code/modules/power/rtg.dm @@ -97,6 +97,7 @@ /obj/machinery/power/rtg/abductor/fire_act(exposed_temperature, exposed_volume) overload() -/obj/machinery/power/rtg/abductor/tesla_act() - ..() //extend the zap - overload() +/obj/machinery/power/rtg/abductor/zap_act(power, zap_flags, shocked_objects) + . = ..() //extend the zap + if(zap_flags & ZAP_MACHINE_EXPLOSIVE) + overload() diff --git a/code/modules/power/singularity/collector.dm b/code/modules/power/singularity/collector.dm index 68a6b34216..651892e5b1 100644 --- a/code/modules/power/singularity/collector.dm +++ b/code/modules/power/singularity/collector.dm @@ -72,7 +72,11 @@ loaded_tank.air_contents.gases[/datum/gas/oxygen] -= gasdrained loaded_tank.air_contents.gases[/datum/gas/carbon_dioxide] += gasdrained*2 GAS_GARBAGE_COLLECT(loaded_tank.air_contents.gases) - SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, stored_power*RAD_COLLECTOR_MINING_CONVERSION_RATE) + var/bitcoins_mined = stored_power*RAD_COLLECTOR_MINING_CONVERSION_RATE + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_ENG) + if(D) + D.adjust_money(bitcoins_mined) + SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, bitcoins_mined) last_push = stored_power stored_power = 0 diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index d57f78e5b6..0d182e0a1b 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -75,7 +75,7 @@ /obj/machinery/power/emitter/ComponentInitialize() . = ..() - AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) + AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) /obj/machinery/power/emitter/RefreshParts() var/max_firedelay = 120 diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index 950e34098c..af2237a426 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -61,7 +61,7 @@ field_generator power level display /obj/machinery/field/generator/ComponentInitialize() . = ..() - AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) + AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) /obj/machinery/field/generator/process() if(active == FG_ONLINE) diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index ed3a098dae..8bf20fddc6 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -127,7 +127,7 @@ /obj/singularity/narsie/mezzer() - for(var/mob/living/carbon/M in viewers(consume_range, src)) + for(var/mob/living/carbon/M in fov_viewers(consume_range, src)) if(M.stat == CONSCIOUS) if(!iscultist(M)) to_chat(M, "You feel conscious thought crumble away in an instant as you gaze upon [src.name]...") diff --git a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm index 59792b6539..e33116b02c 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm @@ -79,8 +79,7 @@ construction_state = PA_CONSTRUCTION_UNSECURED did_something = TRUE else if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/CC = W - if(CC.use(1)) + if(W.use_tool(src, user, 0, 1)) user.visible_message("[user.name] adds wires to the [name].", \ "You add some wires.") construction_state = PA_CONSTRUCTION_PANEL_OPEN diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/power/singularity/particle_accelerator/particle_control.dm index af83f7ebca..957ceb986f 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_control.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_control.dm @@ -288,8 +288,7 @@ construction_state = PA_CONSTRUCTION_UNSECURED did_something = TRUE else if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/CC = W - if(CC.use(1)) + if(W.use_tool(src, user, 0, 1)) user.visible_message("[user.name] adds wires to the [name].", \ "You add some wires.") construction_state = PA_CONSTRUCTION_PANEL_OPEN diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 76eeeae205..025784e909 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -119,14 +119,13 @@ /obj/singularity/Bump(atom/A) + set waitfor = FALSE consume(A) - return - /obj/singularity/Bumped(atom/movable/AM) + set waitfor = FALSE consume(AM) - /obj/singularity/process() if(current_size >= STAGE_TWO) move() @@ -268,6 +267,7 @@ /obj/singularity/proc/eat() + set waitfor = FALSE for(var/tile in spiral_range_turfs(grav_pull, src)) var/turf/T = tile if(!T || !isturf(loc)) @@ -284,8 +284,6 @@ else consume(X) CHECK_TICK - return - /obj/singularity/proc/consume(atom/A) var/gain = A.singularity_act(current_size, src) @@ -295,8 +293,6 @@ name = "supermatter-charged [initial(name)]" consumedSupermatter = 1 set_light(10) - return - /obj/singularity/proc/move(force_move = 0) if(!move_self) diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index 41ed28f0a5..85999707a2 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -125,15 +125,12 @@ to_chat(user, "You start building the power terminal...") playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1) - if(do_after(user, 20, target = src) && C.get_amount() >= 10) - if(C.get_amount() < 10 || !C) - return + if(C.use_tool(src, user, 20, 10)) var/obj/structure/cable/N = T.get_cable_node() //get the connecting node cable, if there's one if (prob(50) && electrocute_mob(usr, N, N, 1, TRUE)) //animate the electrocution if uncautious and unlucky do_sparks(5, TRUE, src) return - C.use(10) user.visible_message(\ "[user.name] has built a power terminal.",\ "You build the power terminal.") diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 650961e2f4..1350c36348 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -249,7 +249,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) add_overlay(causality_field, TRUE) var/speaking = "[emergency_alert] The supermatter has reached critical integrity failure. Emergency causality destabilization field has been activated." - radio.talk_into(src, speaking, common_channel, language = get_default_language()) + radio.talk_into(src, speaking, common_channel, language = get_selected_language()) for(var/i in SUPERMATTER_COUNTDOWN_TIME to 0 step -10) if(damage < explosion_point) // Cutting it a bit close there engineers radio.talk_into(src, "[safe_alert] Failsafe has been disengaged.", common_channel) @@ -433,7 +433,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) env.merge(removed) air_update_turf() - for(var/mob/living/carbon/human/l in view(src, HALLUCINATION_RANGE(power))) // If they can see it without mesons on. Bad on them. + for(var/mob/living/carbon/human/l in fov_viewers(HALLUCINATION_RANGE(power), src)) // If they can see it without mesons on. Bad on them. if(!istype(l.glasses, /obj/item/clothing/glasses/meson)) var/D = sqrt(1 / max(1, get_dist(l, src))) l.hallucination += power * config_hallucination_power * D @@ -559,14 +559,9 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) dust_mob(user, cause = "alien attack") /obj/machinery/power/supermatter_crystal/attack_animal(mob/living/simple_animal/S) - var/murder - if(!S.melee_damage_upper && !S.melee_damage_lower) - murder = S.friendly - else - murder = S.attacktext dust_mob(S, \ - "[S] unwisely [murder] [src], and [S.p_their()] body burns brilliantly before flashing into ash!", \ - "You unwisely touch [src], and your vision glows brightly as your body crumbles to dust. Oops.", \ + "[S] unwisely [S.attack_verb_continuous] [src], and [S.p_their()] body burns brilliantly before flashing into ash!", \ + "You unwisely [S.attack_verb_simple] [src], and your vision glows brightly as your body crumbles to dust. Oops.", \ "simple animal attack") /obj/machinery/power/supermatter_crystal/attack_robot(mob/user) @@ -666,9 +661,10 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) //Some poor sod got eaten, go ahead and irradiate people nearby. radiation_pulse(src, 3000, 2, TRUE) + var/list/viewers = fov_viewers(world.view, src) for(var/mob/living/L in range(10)) investigate_log("has irradiated [key_name(L)] after consuming [AM].", INVESTIGATE_SUPERMATTER) - if(L in view()) + if(L in viewers) L.show_message("As \the [src] slowly stops resonating, you find your skin covered in new radiation burns.", MSG_VISUAL,\ "The unearthly ringing subsides and you notice you have new radiation burns.", MSG_AUDIBLE) else diff --git a/code/modules/power/tesla/coil.dm b/code/modules/power/tesla/coil.dm index e29ffa865e..eb80548441 100644 --- a/code/modules/power/tesla/coil.dm +++ b/code/modules/power/tesla/coil.dm @@ -73,7 +73,7 @@ return ..() -/obj/machinery/power/tesla_coil/tesla_act(power, tesla_flags, shocked_targets) +/obj/machinery/power/tesla_coil/zap_act(power, zap_flags, shocked_targets) if(anchored && !panel_open) obj_flags |= BEING_SHOCKED //don't lose arc power when it's not connected to anything @@ -81,14 +81,17 @@ var/power_produced = powernet ? power / power_loss : power add_avail(power_produced*input_power_multiplier) flick("coilhit", src) - playsound(src.loc, 'sound/magic/lightningshock.ogg', 100, 1, extrarange = 5) - tesla_zap(src, 5, power_produced, tesla_flags, shocked_targets) + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_ENG) + if(D) + D.adjust_money(min(power_produced, 1)) if(istype(linked_techweb)) linked_techweb.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, min(power_produced, 1)) // x4 coils = ~240/m point bonus for R&D addtimer(CALLBACK(src, .proc/reset_shocked), 10) - tesla_buckle_check(power) + zap_buckle_check(power) + playsound(src.loc, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5) + return power_produced else - ..() + . = ..() /obj/machinery/power/tesla_coil/proc/zap() if((last_zap + zap_cooldown) > world.time || !powernet) @@ -99,8 +102,8 @@ var/power = (powernet.avail/2) add_load(power) playsound(src.loc, 'sound/magic/lightningshock.ogg', 100, 1, extrarange = 5) - tesla_zap(src, 10, power/(coeff/2), TESLA_FUSION_FLAGS) - tesla_buckle_check(power/(coeff/2)) + tesla_zap(src, 10, power/(coeff/2), ZAP_FUSION_FLAGS) + zap_buckle_check(power/(coeff/2)) // Tesla R&D researcher /obj/machinery/power/tesla_coil/research @@ -110,20 +113,23 @@ circuit = /obj/item/circuitboard/machine/tesla_coil/research power_loss = 20 // something something, high voltage + resistance -/obj/machinery/power/tesla_coil/research/tesla_act(power, tesla_flags, shocked_things) +/obj/machinery/power/tesla_coil/research/zap_act(power, zap_flags, shocked_targets) if(anchored && !panel_open) obj_flags |= BEING_SHOCKED var/power_produced = powernet ? power / power_loss : power add_avail(power_produced*input_power_multiplier) flick("rpcoilhit", src) - playsound(src.loc, 'sound/magic/lightningshock.ogg', 100, 1, extrarange = 5) - tesla_zap(src, 5, power_produced, tesla_flags, shocked_things) + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_ENG) + if(D) + D.adjust_money(min(power_produced, 3)) if(istype(linked_techweb)) linked_techweb.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, min(power_produced, 3)) // x4 coils with a pulse per second or so = ~720/m point bonus for R&D addtimer(CALLBACK(src, .proc/reset_shocked), 10) - tesla_buckle_check(power) + zap_buckle_check(power) + playsound(src.loc, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5) + return power_produced else - ..() + . = ..() /obj/machinery/power/tesla_coil/research/default_unfasten_wrench(mob/user, obj/item/wrench/W, time = 20) . = ..() @@ -174,9 +180,10 @@ return ..() -/obj/machinery/power/grounding_rod/tesla_act(var/power) +/obj/machinery/power/grounding_rod/zap_act(var/power) if(anchored && !panel_open) flick("grounding_rodhit", src) - tesla_buckle_check(power) + zap_buckle_check(power) + return 0 else - ..() + . = ..() diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index e98fe3c88e..06e5d27f6d 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -1,5 +1,14 @@ #define TESLA_DEFAULT_POWER 1738260 #define TESLA_MINI_POWER 869130 +//Zap constants, speeds up targeting +#define BIKE (COIL + 1) +#define COIL (ROD + 1) +#define ROD (RIDE + 1) +#define RIDE (LIVING + 1) +#define LIVING (MACHINERY + 1) +#define MACHINERY (BLOB + 1) +#define BLOB (STRUCTURE + 1) +#define STRUCTURE (1) /obj/singularity/energy_ball name = "energy ball" @@ -32,6 +41,9 @@ /obj/singularity/energy_ball/ex_act(severity, target) return +/obj/singularity/energy_ball/consume(severity, target) + return + /obj/singularity/energy_ball/Destroy() if(orbiting && istype(orbiting.parent, /obj/singularity/energy_ball)) var/obj/singularity/energy_ball/EB = orbiting.parent @@ -39,7 +51,7 @@ for(var/ball in orbiting_balls) var/obj/singularity/energy_ball/EB = ball - qdel(EB) + QDEL_NULL(EB) . = ..() @@ -55,12 +67,12 @@ move_the_basket_ball(4 + orbiting_balls.len * 1.5) - playsound(src.loc, 'sound/magic/lightningbolt.ogg', 100, 1, extrarange = 30) + playsound(src.loc, 'sound/magic/lightningbolt.ogg', 100, TRUE, extrarange = 30) pixel_x = 0 pixel_y = 0 - tesla_zap(src, 7, TESLA_DEFAULT_POWER, TRUE) + tesla_zap(src, 7, TESLA_DEFAULT_POWER) pixel_x = -32 pixel_y = -32 @@ -73,7 +85,7 @@ /obj/singularity/energy_ball/examine(mob/user) . = ..() if(orbiting_balls.len) - . += "The amount of orbiting mini-balls is [orbiting_balls.len]." + . += "There are [orbiting_balls.len] mini-balls orbiting it." /obj/singularity/energy_ball/proc/move_the_basket_ball(var/move_amount) @@ -96,7 +108,7 @@ energy_to_lower = energy_to_raise - 20 energy_to_raise = energy_to_raise * 1.25 - playsound(src.loc, 'sound/magic/lightning_chargeup.ogg', 100, 1, extrarange = 30) + playsound(src.loc, 'sound/magic/lightning_chargeup.ogg', 100, TRUE, extrarange = 30) addtimer(CALLBACK(src, .proc/new_mini_ball), 100) else if(energy < energy_to_lower && orbiting_balls.len) @@ -132,22 +144,19 @@ /obj/singularity/energy_ball/attack_tk(mob/user) if(iscarbon(user)) var/mob/living/carbon/C = user - log_game("[key_name(C)] has been disintegrated by a telekenetic grab on a tesla ball.") to_chat(C, "That was a shockingly dumb idea.") - C.visible_message("A bright flare of lightning is seen from [C]'s head, shortly before you hear a sickening sizzling!") var/obj/item/organ/brain/rip_u = locate(/obj/item/organ/brain) in C.internal_organs - rip_u.Remove() + C.ghostize(0) qdel(rip_u) - return - return ..() + C.death() /obj/singularity/energy_ball/orbit(obj/singularity/energy_ball/target) if (istype(target)) target.orbiting_balls += src GLOB.poi_list -= src target.dissipate_strength = target.orbiting_balls.len - . = ..() + /obj/singularity/energy_ball/stop_orbit() if (orbiting && istype(orbiting.parent, /obj/singularity/energy_ball)) var/obj/singularity/energy_ball/orbitingball = orbiting.parent @@ -171,20 +180,19 @@ var/mob/living/carbon/C = A C.dust() -/proc/tesla_zap(atom/source, zap_range = 3, power, tesla_flags = TESLA_DEFAULT_FLAGS, list/shocked_targets) +/proc/tesla_zap(atom/source, zap_range = 3, power, zap_flags = ZAP_DEFAULT_FLAGS, list/shocked_targets) + if(QDELETED(source)) + return . = source.dir if(power < 1000) return - var/closest_dist = 0 - var/closest_atom - var/obj/machinery/power/tesla_coil/closest_tesla_coil - var/obj/machinery/power/grounding_rod/closest_grounding_rod - var/mob/living/closest_mob - var/obj/machinery/closest_machine - var/obj/structure/closest_structure - var/obj/structure/blob/closest_blob - var/static/things_to_shock = typecacheof(list(/obj/machinery, /mob/living, /obj/structure)) + /* + THIS IS SO FUCKING UGLY AND I HATE IT, but I can't make it nice without making it slower, check*N rather then n. So we're stuck with it. + */ + var/atom/closest_atom + var/closest_type = 0 + var/static/things_to_shock = typecacheof(list(/obj/machinery, /mob/living, /obj/structure, /obj/vehicle/ridden)) var/static/blacklisted_tesla_types = typecacheof(list(/obj/machinery/atmospherics, /obj/machinery/power/emitter, /obj/machinery/field/generator, @@ -205,112 +213,133 @@ /obj/machinery/gateway, /obj/structure/lattice, /obj/structure/grille, - /obj/machinery/the_singularitygen/tesla, /obj/structure/frame/machine)) - for(var/A in typecache_filter_multi_list_exclusion(oview(source, zap_range+2), things_to_shock, blacklisted_tesla_types)) - if(!(tesla_flags & TESLA_ALLOW_DUPLICATES) && LAZYACCESS(shocked_targets, A)) + //Ok so we are making an assumption here. We assume that view() still calculates from the center out. + //This means that if we find an object we can assume it is the closest one of its type. This is somewhat of a speed increase. + //This also means we have no need to track distance, as the doview() proc does it all for us. + + //Darkness fucks oview up hard. I've tried dview() but it doesn't seem to work + //I hate existance + for(var/a in typecache_filter_multi_list_exclusion(oview(zap_range+2, source), things_to_shock, blacklisted_tesla_types)) + var/atom/A = a + if(!(zap_flags & ZAP_ALLOW_DUPLICATES) && LAZYACCESS(shocked_targets, A)) continue + if(closest_type >= BIKE) + break - if(istype(A, /obj/machinery/power/tesla_coil)) - var/dist = get_dist(source, A) - var/obj/machinery/power/tesla_coil/C = A - if(dist <= zap_range && (dist < closest_dist || !closest_tesla_coil) && !(C.obj_flags & BEING_SHOCKED)) - closest_dist = dist - + else if(istype(A, /obj/vehicle/ridden/bicycle))//God's not on our side cause he hates idiots. + var/obj/vehicle/ridden/bicycle/B = A + if(!(B.obj_flags & BEING_SHOCKED) && B.can_buckle)//Gee goof thanks for the boolean //we use both of these to save on istype and typecasting overhead later on //while still allowing common code to run before hand - closest_tesla_coil = C - closest_atom = C + closest_type = BIKE + closest_atom = B - - else if(closest_tesla_coil) + else if(closest_type >= COIL) continue //no need checking these other things - else if(istype(A, /obj/machinery/power/grounding_rod)) - var/dist = get_dist(source, A)-2 - if(dist <= zap_range && (dist < closest_dist || !closest_grounding_rod)) - closest_grounding_rod = A - closest_atom = A - closest_dist = dist + else if(istype(A, /obj/machinery/power/tesla_coil)) + var/obj/machinery/power/tesla_coil/C = A + if(!(C.obj_flags & BEING_SHOCKED)) + closest_type = COIL + closest_atom = C - else if(closest_grounding_rod) + else if(closest_type >= ROD) + continue + + else if(istype(A, /obj/machinery/power/grounding_rod)) + closest_type = ROD + closest_atom = A + + else if(closest_type >= RIDE) + continue + + else if(istype(A,/obj/vehicle/ridden)) + var/obj/vehicle/ridden/R = A + if(R.can_buckle && !(R.obj_flags & BEING_SHOCKED)) + closest_type = RIDE + closest_atom = A + + else if(closest_type >= LIVING) continue else if(isliving(A)) - var/dist = get_dist(source, A) var/mob/living/L = A - if(dist <= zap_range && (dist < closest_dist || !closest_mob) && L.stat != DEAD && !(L.flags_1 & TESLA_IGNORE_1)) - closest_mob = L + if(L.stat != DEAD && !(HAS_TRAIT(L, TRAIT_TESLA_SHOCKIMMUNE)) && !(L.flags_1 & SHOCKED_1)) + closest_type = LIVING closest_atom = A - closest_dist = dist - else if(closest_mob) + else if(closest_type >= MACHINERY) continue else if(ismachinery(A)) var/obj/machinery/M = A - var/dist = get_dist(source, A) - if(dist <= zap_range && (dist < closest_dist || !closest_machine) && !(M.obj_flags & BEING_SHOCKED)) - closest_machine = M + if(!(M.obj_flags & BEING_SHOCKED)) + closest_type = MACHINERY closest_atom = A - closest_dist = dist - else if(closest_mob) + else if(closest_type >= BLOB) continue else if(istype(A, /obj/structure/blob)) var/obj/structure/blob/B = A - var/dist = get_dist(source, A) - if(dist <= zap_range && (dist < closest_dist || !closest_tesla_coil) && !(B.obj_flags & BEING_SHOCKED)) - closest_blob = B + if(!(B.obj_flags & BEING_SHOCKED)) + closest_type = BLOB closest_atom = A - closest_dist = dist - else if(closest_blob) + else if(closest_type >= STRUCTURE) continue else if(isstructure(A)) var/obj/structure/S = A - var/dist = get_dist(source, A) - if(dist <= zap_range && (dist < closest_dist || !closest_tesla_coil) && !(S.obj_flags & BEING_SHOCKED)) - closest_structure = S + if(!(S.obj_flags & BEING_SHOCKED)) + closest_type = STRUCTURE closest_atom = A - closest_dist = dist //Alright, we've done our loop, now lets see if was anything interesting in range - if(closest_atom) - //common stuff - source.Beam(closest_atom, icon_state="lightning[rand(1,12)]", time=5, maxdistance = INFINITY) - if(!(tesla_flags & TESLA_ALLOW_DUPLICATES)) - LAZYSET(shocked_targets, closest_atom, TRUE) - var/zapdir = get_dir(source, closest_atom) - if(zapdir) - . = zapdir + if(!closest_atom) + return + //common stuff + source.Beam(closest_atom, icon_state="lightning[rand(1,12)]", time=5, maxdistance = INFINITY) + if(!(zap_flags & ZAP_ALLOW_DUPLICATES)) + LAZYSET(shocked_targets, closest_atom, TRUE) + var/zapdir = get_dir(source, closest_atom) + if(zapdir) + . = zapdir - //per type stuff: - if(closest_tesla_coil) - closest_tesla_coil.tesla_act(power, tesla_flags, shocked_targets) + var/next_range = 3 + if(closest_type == COIL) + next_range = 5 - else if(closest_grounding_rod) - closest_grounding_rod.tesla_act(power, tesla_flags, shocked_targets) - - else if(closest_mob) - var/shock_damage = (tesla_flags & TESLA_MOB_DAMAGE)? (min(round(power/600), 90) + rand(-5, 5)) : 0 - closest_mob.electrocute_act(shock_damage, source, 1, SHOCK_TESLA | ((tesla_flags & TESLA_MOB_STUN) ? NONE : SHOCK_NOSTUN)) + if(closest_type == LIVING) + var/mob/living/closest_mob = closest_atom + closest_mob.set_shocked() + addtimer(CALLBACK(closest_mob, /mob/living/proc/reset_shocked), 10) + var/shock_damage = (zap_flags & ZAP_MOB_DAMAGE) ? (min(round(power/600), 90) + rand(-5, 5)) : 0 + closest_mob.electrocute_act(shock_damage, source, 1, SHOCK_TESLA | ((zap_flags & ZAP_MOB_STUN) ? NONE : SHOCK_NOSTUN)) if(issilicon(closest_mob)) var/mob/living/silicon/S = closest_mob - if((tesla_flags & TESLA_MOB_STUN) && (tesla_flags & TESLA_MOB_DAMAGE)) + if((zap_flags & ZAP_MOB_STUN) && (zap_flags & ZAP_MOB_DAMAGE)) S.emp_act(EMP_LIGHT) - tesla_zap(S, 7, power / 1.5, tesla_flags, shocked_targets) // metallic folks bounce it further + next_range = 7 // metallic folks bounce it further else - tesla_zap(closest_mob, 5, power / 1.5, tesla_flags, shocked_targets) + next_range = 5 + power /= 1.5 - else if(closest_machine) - closest_machine.tesla_act(power, tesla_flags, shocked_targets) + else + power = closest_atom.zap_act(power, zap_flags, shocked_targets) + if(prob(20))//I know I know + tesla_zap(closest_atom, next_range, power * 0.5, zap_flags, shocked_targets) + tesla_zap(closest_atom, next_range, power * 0.5, zap_flags, shocked_targets) + else + tesla_zap(closest_atom, next_range, power, zap_flags, shocked_targets) - else if(closest_blob) - closest_blob.tesla_act(power, tesla_flags, shocked_targets) - - else if(closest_structure) - closest_structure.tesla_act(power, tesla_flags, shocked_targets) +#undef BIKE +#undef COIL +#undef ROD +#undef RIDE +#undef LIVING +#undef MACHINERY +#undef BLOB +#undef STRUCTURE diff --git a/code/modules/power/tesla/generator.dm b/code/modules/power/tesla/generator.dm index 53d7010806..260f4128bc 100644 --- a/code/modules/power/tesla/generator.dm +++ b/code/modules/power/tesla/generator.dm @@ -5,6 +5,6 @@ icon_state = "TheSingGen" creation_type = /obj/singularity/energy_ball -/obj/machinery/the_singularitygen/tesla/tesla_act(power, tesla_flags) - if(tesla_flags & TESLA_MACHINE_EXPLOSIVE) +/obj/machinery/the_singularitygen/tesla/zap_act(power, zap_flags) + if(zap_flags & ZAP_MACHINE_EXPLOSIVE) energy += power diff --git a/code/modules/procedural_mapping/mapGenerators/repair.dm b/code/modules/procedural_mapping/mapGenerators/repair.dm index 20ba10b0e1..d9380a40dd 100644 --- a/code/modules/procedural_mapping/mapGenerators/repair.dm +++ b/code/modules/procedural_mapping/mapGenerators/repair.dm @@ -26,8 +26,8 @@ var/z_offset = SSmapping.station_start var/list/bounds for (var/path in SSmapping.config.GetFullMapPaths()) - var/datum/parsed_map/parsed = load_map(file(path), 1, 1, z_offset, measureOnly = FALSE, no_changeturf = FALSE, cropMap=TRUE, x_lower = mother1.x_low, y_lower = mother1.y_low, x_upper = mother1.x_high, y_upper = mother1.y_high) - bounds = parsed?.bounds + var/datum/parsed_map/parsed = load_map(file(path), 1, 1, z_offset, orientation = SSmapping.config.orientation, cropMap = TRUE, x_lower = mother1.x_low, y_lower = mother1.y_low, x_upper = mother1.x_high, y_upper = mother1.y_high) + bounds = parsed.bounds z_offset += bounds[MAP_MAXZ] - bounds[MAP_MINZ] + 1 var/list/obj/machinery/atmospherics/atmos_machines = list() diff --git a/code/modules/projectiles/ammunition/_firing.dm b/code/modules/projectiles/ammunition/_firing.dm index 848163d658..1a6786524c 100644 --- a/code/modules/projectiles/ammunition/_firing.dm +++ b/code/modules/projectiles/ammunition/_firing.dm @@ -31,6 +31,10 @@ else BB.def_zone = user.zone_selected BB.suppressed = quiet + + if(isgun(fired_from)) + var/obj/item/gun/G = fired_from + BB.damage *= G.projectile_damage_multiplier if(reagents && BB.reagents) reagents.trans_to(BB, reagents.total_volume) //For chemical darts/bullets diff --git a/code/modules/projectiles/boxes_magazines/_box_magazine.dm b/code/modules/projectiles/boxes_magazines/_box_magazine.dm index 594734c86a..8ebddaa24f 100644 --- a/code/modules/projectiles/boxes_magazines/_box_magazine.dm +++ b/code/modules/projectiles/boxes_magazines/_box_magazine.dm @@ -113,7 +113,7 @@ /obj/item/ammo_box/update_icon() . = ..() - desc = "[initial(desc)] There are [stored_ammo.len] shell\s left!" + desc = "[initial(desc)] There [stored_ammo.len == 1 ? "is" : "are"] [stored_ammo.len] shell\s left!" for (var/material in bullet_cost) var/material_amount = bullet_cost[material] material_amount = (material_amount*stored_ammo.len) + base_cost[material] diff --git a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm index 81ae026138..597c7203b4 100644 --- a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm +++ b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm @@ -121,3 +121,51 @@ icon_state = "foambox_riot" ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot custom_materials = list(/datum/material/iron = 50000) + +//Shotgun clips +/obj/item/ammo_box/shotgun + name = "stripper clip (shotgun shells)" + desc = "A stripper clip, designed to help with loading a shotgun slightly faster." + icon = 'icons/obj/ammo.dmi' + icon_state = "shotgunclip" + caliber = "shotgun" // slapped in to allow shell mix n match + ammo_type = /obj/item/ammo_casing/shotgun + max_ammo = 4 + var/pixeloffsetx = 4 + start_empty = TRUE + +/obj/item/ammo_box/shotgun/update_overlays() + . = ..() + if(stored_ammo.len) + var/offset = -4 + for(var/A in stored_ammo) + var/obj/item/ammo_casing/shotgun/C = A + offset += pixeloffsetx + var/mutable_appearance/shell_overlay = mutable_appearance(icon, "[initial(C.icon_state)]-clip") + shell_overlay.pixel_x += offset + shell_overlay.appearance_flags = RESET_COLOR + . += shell_overlay + +/obj/item/ammo_box/shotgun/loaded + start_empty = FALSE + +/obj/item/ammo_box/shotgun/loaded/rubbershot + ammo_type = /obj/item/ammo_casing/shotgun/rubbershot + +/obj/item/ammo_box/shotgun/loaded/buckshot + ammo_type = /obj/item/ammo_casing/shotgun/buckshot + +/obj/item/ammo_box/shotgun/loaded/beanbag + ammo_type = /obj/item/ammo_casing/shotgun/beanbag + +/obj/item/ammo_box/shotgun/loaded/stunslug + ammo_type = /obj/item/ammo_casing/shotgun/stunslug + +/obj/item/ammo_box/shotgun/loaded/techshell + ammo_type = /obj/item/ammo_casing/shotgun/techshell + +/obj/item/ammo_box/shotgun/loaded/incendiary + ammo_type = /obj/item/ammo_casing/shotgun/incendiary + +/obj/item/ammo_box/shotgun/loaded/dart + ammo_type = /obj/item/ammo_casing/shotgun/dart diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 9c1a23174e..0f398b6d3b 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -77,13 +77,15 @@ var/dualwield_spread_mult = 1 //dualwield spread multiplier + /// Just 'slightly' snowflakey way to modify projectile damage for projectiles fired from this gun. + var/projectile_damage_multiplier = 1 + /obj/item/gun/Initialize() . = ..() - if(pin) - if(no_pin_required) - pin = null - else - pin = new pin(src) + if(no_pin_required) + pin = null + else if(pin) + pin = new pin(src) if(gun_light) alight = new (src) if(zoomable) @@ -212,7 +214,7 @@ var/loop_counter = 0 bonus_spread += getinaccuracy(user) //CIT CHANGE - adds bonus spread while not aiming - if(ishuman(user) && user.a_intent == INTENT_HARM) + if(ishuman(user) && user.a_intent == INTENT_HARM && weapon_weight <= WEAPON_LIGHT) var/mob/living/carbon/human/H = user for(var/obj/item/gun/G in H.held_items) if(G == src || G.weapon_weight >= WEAPON_MEDIUM) diff --git a/code/modules/projectiles/guns/ballistic/bow.dm b/code/modules/projectiles/guns/ballistic/bow.dm index 3f3d2c6f47..4bd7d34fe2 100644 --- a/code/modules/projectiles/guns/ballistic/bow.dm +++ b/code/modules/projectiles/guns/ballistic/bow.dm @@ -59,7 +59,7 @@ /obj/item/gun/ballistic/bow/pipe name = "pipe bow" - desc = "Some sort of pipe made projectile weapon made of a silk string and lots of bending. Used to fire arrows." + desc = "Some sort of pipe made projectile weapon made of a durathread string and lots of bending. Used to fire arrows." icon_state = "pipebow" item_state = "pipebow" force = 0 diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index b43ac3057a..afe2b9ca3e 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -331,8 +331,7 @@ /obj/item/gun/ballistic/revolver/doublebarrel/improvised/attackby(obj/item/A, mob/user, params) ..() if(istype(A, /obj/item/stack/cable_coil) && !sawn_off) - var/obj/item/stack/cable_coil/C = A - if(C.use(10)) + if(A.use_tool(src, user, 0, 10, max_level = JOB_SKILL_BASIC)) slot_flags = ITEM_SLOT_BACK to_chat(user, "You tie the lengths of cable to the shotgun, making a sling.") slung = TRUE diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm index f8ddcb5aae..2af25971f3 100644 --- a/code/modules/projectiles/guns/misc/beam_rifle.dm +++ b/code/modules/projectiles/guns/misc/beam_rifle.dm @@ -295,7 +295,7 @@ if(istype(object, /obj/screen) && !istype(object, /obj/screen/click_catcher)) return process_aim() - if(fire_check()) + if(fire_check() && can_trigger_gun(M)) sync_ammo() do_fire(M.client.mouseObject, M, FALSE, M.client.mouseParams, M.zone_selected) stop_aiming() diff --git a/code/modules/projectiles/pins.dm b/code/modules/projectiles/pins.dm index 8a1db49762..cef730366e 100644 --- a/code/modules/projectiles/pins.dm +++ b/code/modules/projectiles/pins.dm @@ -13,11 +13,16 @@ var/pin_removeable = 0 // Can be replaced by any pin. var/obj/item/gun/gun -/obj/item/firing_pin/New(newloc) - ..() +/obj/item/firing_pin/Initialize(newloc) + . = ..() if(istype(newloc, /obj/item/gun)) gun = newloc +/obj/item/firing_pin/Destroy() + if(gun) + gun.pin = null + return ..() + /obj/item/firing_pin/afterattack(atom/target, mob/user, proximity_flag) . = ..() if(proximity_flag) @@ -224,24 +229,6 @@ suit_requirement = /obj/item/clothing/suit/bluetag tagcolor = "blue" -/obj/item/firing_pin/Destroy() - if(gun) - gun.pin = null - return ..() - -//Station Locked - -/obj/item/firing_pin/away - name = "station locked pin" - desc = "A firing pin that only will fire when off the station." - -/obj/item/firing_pin/away/pin_auth(mob/living/user) - var/area/station_area = get_area(src) - if(!station_area || is_station_level(station_area.z)) - to_chat(user, "The pin beeps, refusing to fire.") - return FALSE - return TRUE - /obj/item/firing_pin/security_level name = "security level firing pin" desc = "A sophisticated firing pin that authorizes operation based on its settings and current security level." @@ -325,3 +312,18 @@ /obj/item/firing_pin/security_level/pin_auth(mob/living/user) return (only_lethals && !(gun.chambered?.harmful)) || ISINRANGE(GLOB.security_level, min_sec_level, max_sec_level) + +// Explorer Firing Pin- Prevents use on station Z-Level, so it's justifiable to give Explorers guns that don't suck. +/obj/item/firing_pin/explorer + name = "outback firing pin" + desc = "A firing pin used by the austrailian defense force, retrofit to prevent weapon discharge on the station." + icon_state = "firing_pin_explorer" + fail_message = "CANNOT FIRE WHILE ON STATION, MATE!" + +// This checks that the user isn't on the station Z-level. +/obj/item/firing_pin/explorer/pin_auth(mob/living/user) + var/turf/station_check = get_turf(user) + if(!station_check||is_station_level(station_check.z)) + to_chat(user, "You cannot use your weapon while on the station!") + return FALSE + return TRUE diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 432ef97dcb..213bc35b52 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -1,6 +1,10 @@ #define MOVES_HITSCAN -1 //Not actually hitscan but close as we get without actual hitscan. #define MUZZLE_EFFECT_PIXEL_INCREMENT 17 //How many pixels to move the muzzle flash up so your character doesn't look like they're shitting out lasers. +/// Minimum projectile pixels to move before it animate()S, below this it's a direct set. +#define MINIMUM_PIXELS_TO_ANIMATE 4 +/// Pixels to instantly travel on firing. +#define PROJECTILE_FIRING_INSTANT_TRAVEL_AMOUNT 16 /obj/item/projectile name = "projectile" @@ -12,7 +16,9 @@ pass_flags = PASSTABLE mouse_opacity = MOUSE_OPACITY_TRANSPARENT movement_type = FLYING + animate_movement = NO_STEPS hitsound = 'sound/weapons/pierce.ogg' + appearance_flags = PIXEL_SCALE var/hitsound_wall = "" resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF @@ -32,12 +38,19 @@ //Fired processing vars var/fired = FALSE //Have we been fired yet var/paused = FALSE //for suspending the projectile midair - var/last_projectile_move = 0 var/time_offset = 0 var/datum/point/vector/trajectory var/trajectory_ignore_forcemove = FALSE //instructs forceMove to NOT reset our trajectory to the new location! + /// "leftover" pixels for Range() calculation as pixel_move() was moved to simulated semi-pixel movement and Range() is in tiles. + var/pixels_range_leftover = 0 + /// "leftover" tick pixels and stuff yeah, so we don't round off things and introducing tracing inaccuracy. + var/pixels_tick_leftover = 0 + + /// Pixels moved per second. + var/pixels_per_second = TILES_TO_PIXELS(12.5) + /// The number of pixels we increment by. THIS IS NOT SPEED, DO NOT TOUCH THIS UNLESS YOU KNOW WHAT YOU ARE DOING. In general, lower values means more linetrace accuracy up to a point at cost of performance. + var/pixel_increment_amount - var/speed = 0.8 //Amount of deciseconds it takes for projectile to travel var/Angle = 0 var/original_angle = 0 //Angle at firing var/nondirectional_sprite = FALSE //Set TRUE to prevent projectiles from having their sprites rotated based on firing angle @@ -73,12 +86,16 @@ //Homing var/homing = FALSE var/atom/homing_target - var/homing_turn_speed = 10 //Angle per tick. + /// How fast the projectile turns towards its homing targets, in angle per second. + var/homing_turn_speed = 100 var/homing_inaccuracy_min = 0 //in pixels for these. offsets are set once when setting target. var/homing_inaccuracy_max = 0 var/homing_offset_x = 0 var/homing_offset_y = 0 + /// How many deciseconds are each hitscan movement considered. Used for homing and other things that use seconds for timing rather than ticks. + var/hitscan_movement_decisecond_equivalency = 0.1 + var/ignore_source_check = FALSE var/damage = 10 @@ -86,7 +103,8 @@ var/nodamage = 0 //Determines if the projectile will skip any damage inflictions var/flag = "bullet" //Defines what armor to use when it hits things. Must be set to bullet, laser, energy,or bomb var/projectile_type = /obj/item/projectile - var/range = 50 //This will de-increment every step. When 0, it will deletze the projectile. + /// Range of the projectile, de-incrementing every step. The projectile deletes itself at 0. This is in tiles. + var/range = 50 var/decayedRange //stores original range var/reflect_range_decrease = 5 //amount of original range that falls off when reflecting, so it doesn't go forever var/is_reflectable = FALSE // Can it be reflected or not? @@ -118,6 +136,10 @@ permutated = list() decayedRange = range +/** + * Artificially modified to be called at around every world.icon_size pixels of movement. + * WARNING: Range() can only be called once per pixel_increment_amount pixels. + */ /obj/item/projectile/proc/Range() range-- if(range <= 0 && loc) @@ -332,14 +354,15 @@ return TRUE return FALSE +/// one move is a tile. /obj/item/projectile/proc/return_predicted_turf_after_moves(moves, forced_angle) //I say predicted because there's no telling that the projectile won't change direction/location in flight. if(!trajectory && isnull(forced_angle) && isnull(Angle)) return FALSE var/datum/point/vector/current = trajectory if(!current) var/turf/T = get_turf(src) - current = new(T.x, T.y, T.z, pixel_x, pixel_y, isnull(forced_angle)? Angle : forced_angle, SSprojectiles.global_pixel_speed) - var/datum/point/vector/v = current.return_vector_after_increments(moves * SSprojectiles.global_iterations_per_move) + current = new(T.x, T.y, T.z, pixel_x, pixel_y, isnull(forced_angle)? Angle : forced_angle, pixel_increment_amount || SSprojectiles.global_pixel_increment_amount) + var/datum/point/vector/v = current.return_vector_after_increments(TILES_TO_PIXELS(moves) / (pixel_increment_amount || SSprojectiles.global_pixel_increment_amount)) return v.return_turf() /obj/item/projectile/proc/return_pathing_turfs_in_moves(moves, forced_angle) @@ -350,13 +373,20 @@ /obj/item/projectile/Process_Spacemove(movement_dir = 0) return TRUE //Bullets don't drift in space -/obj/item/projectile/process() +/obj/item/projectile/process(wait) if(!loc || !fired || !trajectory) fired = FALSE return PROCESS_KILL if(paused || !isturf(loc)) return - pixel_move(1, FALSE) + + var/ds = (SSprojectiles.flags & SS_TICKER)? (wait * world.tick_lag) : wait + var/required_pixels = (pixels_per_second * ds * 0.1) + pixels_tick_leftover + if(required_pixels >= pixel_increment_amount) + pixels_tick_leftover = MODULUS(required_pixels, pixel_increment_amount) + pixel_move(FLOOR(required_pixels / pixel_increment_amount, 1), FALSE, ds, SSprojectiles.global_projectile_speed_multiplier) + else + pixels_tick_leftover = required_pixels /obj/item/projectile/proc/fire(angle, atom/direct_target) if(fired_from) @@ -379,7 +409,7 @@ qdel(src) return var/turf/target = locate(clamp(starting + xo, 1, world.maxx), clamp(starting + yo, 1, world.maxy), starting.z) - setAngle(Get_Angle(src, target)) + setAngle(get_projectile_angle(src, target)) original_angle = Angle if(!nondirectional_sprite) var/matrix/M = new @@ -388,14 +418,16 @@ trajectory_ignore_forcemove = TRUE forceMove(starting) trajectory_ignore_forcemove = FALSE - trajectory = new(starting.x, starting.y, starting.z, pixel_x, pixel_y, Angle, SSprojectiles.global_pixel_speed) - last_projectile_move = world.time + if(isnull(pixel_increment_amount)) + pixel_increment_amount = SSprojectiles.global_pixel_increment_amount + trajectory = new(starting.x, starting.y, starting.z, pixel_x, pixel_y, Angle, pixel_increment_amount) fired = TRUE if(hitscan) process_hitscan() + return if(!(datum_flags & DF_ISPROCESSING)) START_PROCESSING(SSprojectiles, src) - pixel_move(1, FALSE) //move it now! + pixel_move(round(PROJECTILE_FIRING_INSTANT_TRAVEL_AMOUNT / pixel_increment_amount), FALSE, allow_animation = FALSE) //move it now! /obj/item/projectile/proc/setAngle(new_angle, hitscan_store_segment = TRUE) //wrapper for overrides. Angle = new_angle @@ -440,7 +472,8 @@ else return ..() -/obj/item/projectile/proc/set_pixel_speed(new_speed) +/obj/item/projectile/proc/set_pixel_increment_amount(new_speed) + pixel_increment_amount = new_speed if(trajectory) trajectory.set_speed(new_speed) return TRUE @@ -453,6 +486,7 @@ beam_segments[beam_index] = null //record start. /obj/item/projectile/proc/process_hitscan() + var/ttm = round(world.icon_size / pixel_increment_amount, 1) var/safety = range * 10 record_hitscan_start(RETURN_POINT_VECTOR_INCREMENT(src, Angle, MUZZLE_EFFECT_PIXEL_INCREMENT, 1)) while(loc && !QDELETED(src)) @@ -465,20 +499,33 @@ if(!QDELETED(src)) qdel(src) return //Kill! - pixel_move(1, TRUE) + pixel_move(ttm, TRUE, hitscan_movement_decisecond_equivalency) -/obj/item/projectile/proc/pixel_move(trajectory_multiplier, hitscanning = FALSE) +/** + * The proc to make the projectile go, using a simulated pixel movement line trace. + * Note: deciseconds_equivalent is currently only used for homing, times is the number of times to move pixel_increment_amount. + * Trajectory multiplier directly modifies the factor of pixel_increment_amount to go per time. + * It's complicated, so probably just don'ot mess with this unless you know what you're doing. + */ +/obj/item/projectile/proc/pixel_move(times, hitscanning = FALSE, deciseconds_equivalent = world.tick_lag, trajectory_multiplier = 1, allow_animation = TRUE) if(!loc || !trajectory) return - last_projectile_move = world.time if(!nondirectional_sprite && !hitscanning) var/matrix/M = new M.Turn(Angle) transform = M - if(homing) - process_homing() var/forcemoved = FALSE - for(var/i in 1 to SSprojectiles.global_iterations_per_move) + var/turf/oldloc = loc + var/old_px = pixel_x + var/old_py = pixel_y + for(var/i in 1 to times) + // HOMING START - Too expensive to proccall at this point. + if(homing_target) + // No datum/points, too expensive. + var/angle = closer_angle_difference(Angle, get_projectile_angle(src, homing_target)) + var/max_turn = homing_turn_speed * deciseconds_equivalent * 0.1 + setAngle(Angle + clamp(angle, -max_turn, max_turn)) + // HOMING END trajectory.increment(trajectory_multiplier) var/turf/T = trajectory.return_turf() if(!istype(T)) @@ -498,23 +545,29 @@ pixel_x = trajectory.return_px() pixel_y = trajectory.return_py() else if(T != loc) - step_towards(src, T) + var/safety = CEILING(pixel_increment_amount / world.icon_size, 1) * 2 + 1 + while(T != loc) + if(!--safety) + CRASH("Projectile took more than pixel incrememnt speed times 2 to get to its location, this is probably something seriously scuffed going on.") + step_towards(src, T) + if(QDELETED(src)) + return + pixels_range_leftover += pixel_increment_amount + if(pixels_range_leftover > world.icon_size) + Range() if(QDELETED(src)) return + pixels_range_leftover -= world.icon_size if(!hitscanning && !forcemoved) - pixel_x = trajectory.return_px() - trajectory.mpx * trajectory_multiplier * SSprojectiles.global_iterations_per_move - pixel_y = trajectory.return_py() - trajectory.mpy * trajectory_multiplier * SSprojectiles.global_iterations_per_move - animate(src, pixel_x = trajectory.return_px(), pixel_y = trajectory.return_py(), time = 1, flags = ANIMATION_END_NOW) - Range() - -/obj/item/projectile/proc/process_homing() //may need speeding up in the future performance wise. - if(!homing_target) - return FALSE - var/datum/point/PT = RETURN_PRECISE_POINT(homing_target) - PT.x += clamp(homing_offset_x, 1, world.maxx) - PT.y += clamp(homing_offset_y, 1, world.maxy) - var/angle = closer_angle_difference(Angle, angle_between_points(RETURN_PRECISE_POINT(src), PT)) - setAngle(Angle + clamp(angle, -homing_turn_speed, homing_turn_speed)) + var/traj_px = round(trajectory.return_px(), 1) + var/traj_py = round(trajectory.return_py(), 1) + if(allow_animation && (pixel_increment_amount * times > MINIMUM_PIXELS_TO_ANIMATE)) + pixel_x = ((oldloc.x - x) * world.icon_size) + old_px + pixel_y = ((oldloc.y - y) * world.icon_size) + old_py + animate(src, pixel_x = traj_px, pixel_y = traj_py, time = 1, flags = ANIMATION_END_NOW) + else + pixel_x = traj_px + pixel_y = traj_py /obj/item/projectile/proc/set_homing_target(atom/A) if(!A || (!isturf(A) && !isturf(A.loc))) @@ -564,7 +617,7 @@ if(targloc || !params) yo = targloc.y - curloc.y xo = targloc.x - curloc.x - setAngle(Get_Angle(src, targloc) + spread) + setAngle(get_projectile_angle(src, targloc) + spread) if(isliving(source) && params) var/list/calculated = calculate_projectile_angle_and_pixel_offsets(source, params) @@ -575,7 +628,7 @@ else if(targloc) yo = targloc.y - curloc.y xo = targloc.x - curloc.x - setAngle(Get_Angle(src, targloc) + spread) + setAngle(get_projectile_angle(src, targloc) + spread) else stack_trace("WARNING: Projectile [type] fired without either mouse parameters, or a target atom to aim at!") qdel(src) @@ -687,3 +740,7 @@ /proc/is_energy_reflectable_projectile(atom/A) var/obj/item/projectile/P = A return istype(P) && P.is_reflectable + +#undef MOVES_HITSCAN +#undef MINIMUM_PIXELS_TO_ANIMATE +#undef MUZZLE_EFFECT_PIXEL_INCREMENT diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index ee081d57d6..2f12f0f69b 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -74,7 +74,7 @@ flag = "energy" hitsound = 'sound/weapons/tap.ogg' eyeblur = 0 - speed = 0.6 + pixels_per_second = TILES_TO_PIXELS(16.667) impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser light_color = LIGHT_COLOR_BLUE tracer_type = /obj/effect/projectile/tracer/disabler diff --git a/code/modules/projectiles/projectile/bullets/ferromagnetic.dm b/code/modules/projectiles/projectile/bullets/ferromagnetic.dm index 2d66e25256..78deff601f 100644 --- a/code/modules/projectiles/projectile/bullets/ferromagnetic.dm +++ b/code/modules/projectiles/projectile/bullets/ferromagnetic.dm @@ -3,7 +3,7 @@ damage = 20 armour_penetration = 20 light_range = 3 - speed = 0.6 + pixels_per_second = TILES_TO_PIXELS(16.667) range = 35 light_color = LIGHT_COLOR_RED @@ -39,7 +39,7 @@ armour_penetration = 20 movement_type = FLYING | UNSTOPPABLE range = 20 - speed = 0.8 + pixels_per_second = TILES_TO_PIXELS(12.5) light_range = 4 light_color = LIGHT_COLOR_RED diff --git a/code/modules/projectiles/projectile/bullets/sniper.dm b/code/modules/projectiles/projectile/bullets/sniper.dm index 5e3ae53806..f69b62a149 100644 --- a/code/modules/projectiles/projectile/bullets/sniper.dm +++ b/code/modules/projectiles/projectile/bullets/sniper.dm @@ -2,7 +2,7 @@ /obj/item/projectile/bullet/p50 name =".50 bullet" - speed = 0.4 + pixels_per_second = TILES_TO_PIXELS(25) damage = 70 knockdown = 100 dismemberment = 50 @@ -43,5 +43,5 @@ /obj/item/projectile/bullet/p50/penetrator/shuttle //Nukeop Shuttle Variety icon_state = "gaussstrong" damage = 25 - speed = 0.3 + pixels_per_second = TILES_TO_PIXELS(33.33) range = 16 diff --git a/code/modules/projectiles/projectile/energy/nuclear_particle.dm b/code/modules/projectiles/projectile/energy/nuclear_particle.dm index e08f806fe5..6cbe258560 100644 --- a/code/modules/projectiles/projectile/energy/nuclear_particle.dm +++ b/code/modules/projectiles/projectile/energy/nuclear_particle.dm @@ -5,7 +5,7 @@ pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE flag = "rad" irradiate = 5000 - speed = 0.4 + pixels_per_second = TILES_TO_PIXELS(25) hitsound = 'sound/weapons/emitter2.ogg' impact_type = /obj/effect/projectile/impact/xray var/static/list/particle_colors = list( diff --git a/code/modules/projectiles/projectile/energy/stun.dm b/code/modules/projectiles/projectile/energy/stun.dm index e3449a0c1d..83b753e0a3 100644 --- a/code/modules/projectiles/projectile/energy/stun.dm +++ b/code/modules/projectiles/projectile/energy/stun.dm @@ -10,7 +10,7 @@ jitter = 20 hitsound = 'sound/weapons/taserhit.ogg' range = 14 - speed = 0.6 + pixels_per_second = TILES_TO_PIXELS(16.667) tracer_type = /obj/effect/projectile/tracer/stun muzzle_type = /obj/effect/projectile/muzzle/stun impact_type = /obj/effect/projectile/impact/stun diff --git a/code/modules/projectiles/projectile/energy/tesla.dm b/code/modules/projectiles/projectile/energy/tesla.dm index 2439cee429..1afbdeae25 100644 --- a/code/modules/projectiles/projectile/energy/tesla.dm +++ b/code/modules/projectiles/projectile/energy/tesla.dm @@ -3,7 +3,7 @@ icon_state = "tesla_projectile" impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser var/chain - var/tesla_flags = TESLA_MOB_DAMAGE | TESLA_OBJ_DAMAGE + var/zap_flags = ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE var/zap_range = 3 var/power = 10000 @@ -15,7 +15,7 @@ /obj/item/projectile/energy/tesla/on_hit(atom/target) . = ..() - tesla_zap(target, zap_range, power, tesla_flags) + tesla_zap(target, zap_range, power, zap_flags) qdel(src) /obj/item/projectile/energy/tesla/Destroy() diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index cb5b280c5e..493a02d74c 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -228,7 +228,6 @@ if(!new_mob) return - new_mob.grant_language(/datum/language/common) // Some forms can still wear some items for(var/obj/item/W in contents) @@ -435,12 +434,12 @@ damage = 15 damage_type = BURN nodamage = 0 - speed = 0.3 + pixels_per_second = TILES_TO_PIXELS(33.33) flag = "magic" - var/tesla_power = 20000 - var/tesla_range = 15 - var/tesla_flags = TESLA_MOB_DAMAGE | TESLA_MOB_STUN | TESLA_OBJ_DAMAGE + var/zap_power = 20000 + var/zap_range = 15 + var/zap_flags = ZAP_MOB_DAMAGE | ZAP_MOB_STUN | ZAP_OBJ_DAMAGE var/chain var/mob/living/caster @@ -457,7 +456,7 @@ visible_message("[src] fizzles on contact with [target]!") qdel(src) return BULLET_ACT_BLOCK - tesla_zap(src, tesla_range, tesla_power, tesla_flags) + tesla_zap(src, zap_range, zap_power, zap_flags) qdel(src) /obj/item/projectile/magic/aoe/lightning/Destroy() diff --git a/code/modules/projectiles/projectile/special/curse.dm b/code/modules/projectiles/projectile/special/curse.dm index 99aa922622..d967540e6a 100644 --- a/code/modules/projectiles/projectile/special/curse.dm +++ b/code/modules/projectiles/projectile/special/curse.dm @@ -10,7 +10,7 @@ damage_type = BURN damage = 10 knockdown = 20 - speed = 2 + pixels_per_second = TILES_TO_PIXELS(5) range = 16 movement_type = FLYING | UNSTOPPABLE var/datum/beam/arm diff --git a/code/modules/projectiles/projectile/special/hallucination.dm b/code/modules/projectiles/projectile/special/hallucination.dm index 3aa85c085f..19fd13857a 100644 --- a/code/modules/projectiles/projectile/special/hallucination.dm +++ b/code/modules/projectiles/projectile/special/hallucination.dm @@ -50,7 +50,7 @@ if(M == hal_target) to_chat(hal_target, "[M] is hit by \a [src] in the chest!") hal_apply_effect() - else if(M in view(hal_target)) + else if(M in hal_target.fov_view()) to_chat(hal_target, "[M] is hit by \a [src] in the chest!!") if(damage_type == BRUTE) var/splatter_dir = dir diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index f4c06f39cc..38aafc665f 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -535,7 +535,7 @@ add_reagent(P, cached_results[P]*multiplier, null, chem_temp) - var/list/seen = viewers(4, get_turf(my_atom))//Sound and sight checkers + var/list/seen = fov_viewers(4, get_turf(my_atom))//Sound and sight checkers var/iconhtml = icon2html(cached_my_atom, seen) if(cached_my_atom) if(!ismob(cached_my_atom)) // No bubbling mobs @@ -617,10 +617,7 @@ handle_reactions() update_total() //Reaction sounds and words - var/list/seen = viewers(5, get_turf(my_atom)) - var/iconhtml = icon2html(my_atom, seen) - for(var/mob/M in seen) - to_chat(M, "[iconhtml] [C.mix_message]") + my_atom.visible_message("[icon2html(my_atom, viewers(DEFAULT_MESSAGE_RANGE, src))] [C.mix_message]") /datum/reagents/proc/fermiReact(selected_reaction, cached_temp, cached_pH, reactedVol, targetVol, cached_required_reagents, cached_results, multiplier) var/datum/chemical_reaction/C = selected_reaction diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 7f57dd1723..b85d7aefc9 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -23,7 +23,7 @@ resistance_flags = FIRE_PROOF | ACID_PROOF circuit = /obj/item/circuitboard/machine/chem_dispenser var/obj/item/stock_parts/cell/cell - var/powerefficiency = 0.1 + var/powerefficiency = 0.0666666 var/amount = 30 var/recharge_amount = 10 var/recharge_counter = 0 @@ -387,7 +387,7 @@ /obj/machinery/chem_dispenser/RefreshParts() recharge_amount = initial(recharge_amount) - var/newpowereff = 0.0666666 + var/newpowereff = initial(powerefficiency) for(var/obj/item/stock_parts/cell/P in component_parts) cell = P for(var/obj/item/stock_parts/matter_bin/M in component_parts) @@ -511,12 +511,10 @@ /datum/reagent/consumable/peachjuice ) emagged_reagents = list( - /datum/reagent/consumable/ethanol/thirteenloko, - /datum/reagent/consumable/ethanol/changelingsting, - /datum/reagent/consumable/ethanol/whiskey_cola, /datum/reagent/toxin/mindbreaker, /datum/reagent/toxin/staminatoxin, - /datum/reagent/medicine/cryoxadone + /datum/reagent/medicine/cryoxadone, + /datum/reagent/iron ) /obj/machinery/chem_dispenser/drinks/fullupgrade //fully ugpraded stock parts, emagged @@ -571,13 +569,12 @@ upgrade_reagents2 = null upgrade_reagents3 = null emagged_reagents = list( - /datum/reagent/iron, /datum/reagent/consumable/ethanol/alexander, /datum/reagent/consumable/clownstears, /datum/reagent/toxin/minttoxin, /datum/reagent/consumable/ethanol/atomicbomb, - /datum/reagent/drug/aphrodisiac, - /datum/reagent/drug/aphrodisiacplus + /datum/reagent/consumable/ethanol/thirteenloko, + /datum/reagent/consumable/ethanol/changelingsting ) /obj/machinery/chem_dispenser/drinks/beer/fullupgrade //fully ugpraded stock parts, emagged @@ -723,3 +720,58 @@ component_parts += new /obj/item/stack/sheet/glass(null) component_parts += new /obj/item/stock_parts/cell/bluespace(null) RefreshParts() + +///An unique, less efficient model found in the medbay apothecary room. +/obj/machinery/chem_dispenser/apothecary + name = "apothecary chem dispenser" + desc = "A cheaper chem dispenser meant for small scale medicine production." + icon_state = "minidispenser" + working_state = "minidispenser_working" + nopower_state = "minidispenser_nopower" + circuit = /obj/item/circuitboard/machine/chem_dispenser/apothecary + powerefficiency = 0.0833333 + dispensable_reagents = list( //radium and stable plasma moved to upgrade tier 1 and 2, they've little to do with most medicines anyway. + /datum/reagent/hydrogen, + /datum/reagent/lithium, + /datum/reagent/carbon, + /datum/reagent/nitrogen, + /datum/reagent/oxygen, + /datum/reagent/fluorine, + /datum/reagent/sodium, + /datum/reagent/aluminium, + /datum/reagent/silicon, + /datum/reagent/phosphorus, + /datum/reagent/sulfur, + /datum/reagent/chlorine, + /datum/reagent/potassium, + /datum/reagent/iron, + /datum/reagent/copper, + /datum/reagent/mercury, + /datum/reagent/water, + /datum/reagent/consumable/ethanol, + /datum/reagent/consumable/sugar, + /datum/reagent/toxin/acid, + /datum/reagent/fuel, + /datum/reagent/silver, + /datum/reagent/iodine, + /datum/reagent/bromine + ) + upgrade_reagents = list( + /datum/reagent/oil, + /datum/reagent/ammonia, + /datum/reagent/radium + ) + upgrade_reagents2 = list( + /datum/reagent/acetone, + /datum/reagent/phenol, + /datum/reagent/stable_plasma + ) + upgrade_reagents3 = list( + /datum/reagent/medicine/mine_salve + ) + + emagged_reagents = list( + /datum/reagent/drug/space_drugs, + /datum/reagent/toxin/carpotoxin, + /datum/reagent/medicine/morphine + ) diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm index 25315f457d..38a05cd541 100644 --- a/code/modules/reagents/chemistry/machinery/pandemic.dm +++ b/code/modules/reagents/chemistry/machinery/pandemic.dm @@ -170,7 +170,7 @@ if(!A.mutable) return if(A) - var/new_name = sanitize_name(html_encode(params["name"])) + var/new_name = sanitize_name(html_encode(trim(params["name"], 50))) if(!new_name || ..()) return A.AssignName(new_name) diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 464557f617..b22f34091f 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -1834,7 +1834,7 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/fernet/on_mob_life(mob/living/carbon/M) if(M.nutrition <= NUTRITION_LEVEL_STARVING) M.adjustToxLoss(1*REM, 0) - M.nutrition = max(M.nutrition - 5, 0) + M.adjust_nutrition(-5) M.overeatduration = 0 return ..() @@ -1852,7 +1852,7 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/fernet_cola/on_mob_life(mob/living/carbon/M) if(M.nutrition <= NUTRITION_LEVEL_STARVING) M.adjustToxLoss(0.5*REM, 0) - M.nutrition = max(M.nutrition - 3, 0) + M.adjust_nutrition(-3) M.overeatduration = 0 return ..() @@ -1868,7 +1868,7 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_desc = "A glass of Fanciulli. It's just Manhattan with Fernet." /datum/reagent/consumable/ethanol/fanciulli/on_mob_life(mob/living/carbon/M) - M.nutrition = max(M.nutrition - 5, 0) + M.adjust_nutrition(-5) M.overeatduration = 0 return ..() diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index 62aea28009..b157f328c5 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -692,9 +692,8 @@ M.adjustFireLoss(-0.5, 0) M.adjustToxLoss(-0.5, 0) M.adjustOxyLoss(-0.5, 0) - if(M.nutrition && (M.nutrition - 2 > 0)) - if(!(M.mind && M.mind.assigned_role == "Medical Doctor")) //Drains the nutrition of the holder. Not medical doctors though, since it's the Doctor's Delight! - M.nutrition -= 2 + if(!(M.mind && M.mind.assigned_role == "Medical Doctor")) //Drains the nutrition of the holder. Not medical doctors though, since it's the Doctor's Delight! + M.adjust_nutrition(-2) ..() . = 1 diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index ef4b7f3a53..f1e45d0717 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -559,3 +559,128 @@ var/mob/living/carbon/C = M if(!C.undergoing_cardiac_arrest()) C.set_heartattack(TRUE) + +//aphrodisiac & anaphrodisiac + +/datum/reagent/drug/aphrodisiac + name = "Crocin" + description = "Naturally found in the crocus and gardenia flowers, this drug acts as a natural and safe aphrodisiac." + taste_description = "strawberries" + color = "#FFADFF"//PINK, rgb(255, 173, 255) + can_synth = FALSE + +/datum/reagent/drug/aphrodisiac/on_mob_life(mob/living/M) + if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO)) + if((prob(min(current_cycle/2,5)))) + M.emote(pick("moan","blush")) + if(prob(min(current_cycle/4,10))) + var/aroused_message = pick("You feel frisky.", "You're having trouble suppressing your urges.", "You feel in the mood.") + to_chat(M, "[aroused_message]") + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/list/genits = H.adjust_arousal(current_cycle, aphro = TRUE) // redundant but should still be here + for(var/g in genits) + var/obj/item/organ/genital/G = g + to_chat(M, "[G.arousal_verb]!") + ..() + +/datum/reagent/drug/aphrodisiacplus + name = "Hexacrocin" + description = "Chemically condensed form of basic crocin. This aphrodisiac is extremely powerful and addictive in most animals.\ + Addiction withdrawals can cause brain damage and shortness of breath. Overdosage can lead to brain damage and a \ + permanent increase in libido (commonly referred to as 'bimbofication')." + taste_description = "liquid desire" + color = "#FF2BFF"//dark pink + addiction_threshold = 20 + overdose_threshold = 20 + can_synth = FALSE + +/datum/reagent/drug/aphrodisiacplus/on_mob_life(mob/living/M) + if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO)) + if(prob(5)) + if(prob(current_cycle)) + M.say(pick("Hnnnnngghh...", "Ohh...", "Mmnnn...")) + else + M.emote(pick("moan","blush")) + if(prob(5)) + var/aroused_message + if(current_cycle>25) + aroused_message = pick("You need to fuck someone!", "You're bursting with sexual tension!", "You can't get sex off your mind!") + else + aroused_message = pick("You feel a bit hot.", "You feel strong sexual urges.", "You feel in the mood.", "You're ready to go down on someone.") + to_chat(M, "[aroused_message]") + REMOVE_TRAIT(M,TRAIT_NEVERBONER,APHRO_TRAIT) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/list/genits = H.adjust_arousal(100, aphro = TRUE) // redundant but should still be here + for(var/g in genits) + var/obj/item/organ/genital/G = g + to_chat(M, "[G.arousal_verb]!") + ..() + +/datum/reagent/drug/aphrodisiacplus/addiction_act_stage2(mob/living/M) + if(prob(30)) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2) + ..() +/datum/reagent/drug/aphrodisiacplus/addiction_act_stage3(mob/living/M) + if(prob(30)) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3) + + ..() +/datum/reagent/drug/aphrodisiacplus/addiction_act_stage4(mob/living/M) + if(prob(30)) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 4) + ..() + +/datum/reagent/drug/aphrodisiacplus/overdose_process(mob/living/M) + if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(33)) + if(prob(5) && ishuman(M) && M.has_dna() && (M.client?.prefs.cit_toggles & BIMBOFICATION)) + if(!HAS_TRAIT(M,TRAIT_PERMABONER)) + to_chat(M, "Your libido is going haywire!") + ADD_TRAIT(M,TRAIT_PERMABONER,APHRO_TRAIT) + ..() + +/datum/reagent/drug/anaphrodisiac + name = "Camphor" + description = "Naturally found in some species of evergreen trees, camphor is a waxy substance. When injested by most animals, it acts as an anaphrodisiac\ + , reducing libido and calming them. Non-habit forming and not addictive." + taste_description = "dull bitterness" + taste_mult = 2 + color = "#D9D9D9"//rgb(217, 217, 217) + reagent_state = SOLID + can_synth = FALSE + +/datum/reagent/drug/anaphrodisiac/on_mob_life(mob/living/M) + if(M && M.client?.prefs.arousable && prob(16)) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/list/genits = H.adjust_arousal(-100, aphro = TRUE) + if(genits.len) + to_chat(M, "You no longer feel aroused.") + ..() + +/datum/reagent/drug/anaphrodisiacplus + name = "Hexacamphor" + description = "Chemically condensed camphor. Causes an extreme reduction in libido and a permanent one if overdosed. Non-addictive." + taste_description = "tranquil celibacy" + color = "#D9D9D9"//rgb(217, 217, 217) + reagent_state = SOLID + overdose_threshold = 20 + can_synth = FALSE + +/datum/reagent/drug/anaphrodisiacplus/on_mob_life(mob/living/M) + if(M && M.client?.prefs.arousable) + REMOVE_TRAIT(M,TRAIT_PERMABONER,APHRO_TRAIT) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/list/genits = H.adjust_arousal(-100, aphro = TRUE) + if(genits.len) + to_chat(M, "You no longer feel aroused.") + + ..() + +/datum/reagent/drug/anaphrodisiacplus/overdose_process(mob/living/M) + if(M && M.client?.prefs.arousable && prob(5)) + to_chat(M, "You feel like you'll never feel aroused again...") + ADD_TRAIT(M,TRAIT_NEVERBONER,APHRO_TRAIT) + ..() diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index c7ff3f01c9..0e0056f958 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -13,11 +13,12 @@ taste_mult = 4 value = REAGENT_VALUE_VERY_COMMON var/nutriment_factor = 1 * REAGENTS_METABOLISM + var/max_nutrition = INFINITY var/quality = 0 //affects mood, typically higher for mixed drinks with more complex recipes /datum/reagent/consumable/on_mob_life(mob/living/carbon/M) current_cycle++ - M.nutrition += nutriment_factor + M.adjust_nutrition(nutriment_factor, max_nutrition) M.CheckBloodsuckerEatFood(nutriment_factor) holder.remove_reagent(type, metabolization_rate) @@ -694,13 +695,10 @@ description = "A bioengineered protien-nutrient structure designed to decompose in high saturation. In layman's terms, it won't get you fat." reagent_state = SOLID nutriment_factor = 12 * REAGENTS_METABOLISM + max_nutrition = NUTRITION_LEVEL_FULL - 25 color = "#664330" // rgb: 102, 67, 48 value = REAGENT_VALUE_RARE -/datum/reagent/consumable/nutriment/stabilized/on_mob_life(mob/living/carbon/M) - if(M.nutrition > NUTRITION_LEVEL_FULL - 25) - M.nutrition -= 3*nutriment_factor - ..() ////Lavaland Flora Reagents//// diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index e4973dd2d5..b51e28decf 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -274,7 +274,11 @@ /datum/reagent/medicine/silver_sulfadiazine/overdose_start(mob/living/M) metabolization_rate = 15 * REAGENTS_METABOLISM - M.adjustBruteLoss(2*REM, 0) + ..() + . = 1 + +/datum/reagent/medicine/silver_sulfadiazine/overdose_process(mob/living/M) + M.adjustFireLoss(2*REM, 0) var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) if(L) L.applyOrganDamage(1) @@ -340,8 +344,12 @@ ..() . = 1 -datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M) +/datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M) metabolization_rate = 15 * REAGENTS_METABOLISM + ..() + . = 1 + +/datum/reagent/medicine/styptic_powder/overdose_process(mob/living/M) M.adjustBruteLoss(2*REM, 0) var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) if(L) @@ -413,7 +421,7 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M) /datum/reagent/medicine/mine_salve/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1) if(iscarbon(M) && M.stat != DEAD) if(method in list(INGEST, VAPOR, INJECT)) - M.nutrition -= 5 + M.adjust_nutrition(-5) if(show_message) to_chat(M, "Your stomach feels empty and cramps!") else @@ -1218,15 +1226,15 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M) value = REAGENT_VALUE_VERY_RARE /datum/reagent/medicine/lesser_syndicate_nanites/on_mob_life(mob/living/carbon/M) - M.adjustBruteLoss(-3*REM, FALSE) // hidden gold shh - M.adjustFireLoss(-3*REM, FALSE) - M.adjustOxyLoss(-15, FALSE) - M.adjustToxLoss(-3*REM, FALSE) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -15*REM) - M.adjustCloneLoss(-3*REM, FALSE) - M.adjustStaminaLoss(-20*REM,FALSE) + M.adjustBruteLoss(-2*REM, FALSE) + M.adjustFireLoss(-2*REM, FALSE) + M.adjustOxyLoss(-5*REM, FALSE) + M.adjustToxLoss(-2*REM, FALSE) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -5*REM) + M.adjustCloneLoss(-1.25*REM, FALSE) + M.adjustStaminaLoss(-4*REM,FALSE) if(M.blood_volume < (BLOOD_VOLUME_NORMAL*M.blood_ratio)) - M.blood_volume += 20 // blood fall out man bad + M.blood_volume += 3 ..() . = 1 diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 5fb27bd074..d3ac8fa506 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1735,6 +1735,22 @@ H.facial_hair_style = "Very Long Beard" H.update_hair() +/datum/reagent/baldium + name = "Baldium" + description = "A major cause of hair loss across the world." + reagent_state = LIQUID + color = "#ecb2cf" + taste_description = "bitterness" + +/datum/reagent/baldium/reaction_mob(mob/living/M, method=TOUCH, reac_volume) + if(method == TOUCH || method == VAPOR) + if(M && ishuman(M)) + var/mob/living/carbon/human/H = M + to_chat(H, "Your hair is falling out in clumps!") + H.hair_style = "Bald" + H.facial_hair_style = "Shaved" + H.update_hair() + /datum/reagent/saltpetre name = "Saltpetre" description = "Volatile. Controversial. Third Thing." @@ -2178,3 +2194,93 @@ reagent_state = LIQUID color = "#f7685e" metabolization_rate = REAGENTS_METABOLISM * 0.25 + + +//body bluids +/datum/reagent/consumable/semen + name = "Semen" + description = "Sperm from some animal. Useless for anything but insemination, really." + taste_description = "something salty" + taste_mult = 2 //Not very overpowering flavor + data = list("donor"=null,"viruses"=null,"donor_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null) + reagent_state = LIQUID + color = "#FFFFFF" // rgb: 255, 255, 255 + can_synth = FALSE + nutriment_factor = 0.5 * REAGENTS_METABOLISM + +/datum/reagent/consumable/semen/reaction_turf(turf/T, reac_volume) + if(!istype(T)) + return + if(reac_volume < 10) + return + + var/obj/effect/decal/cleanable/semen/S = locate() in T + if(!S) + S = new(T) + if(data["blood_DNA"]) + S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"])) + +/obj/effect/decal/cleanable/semen + name = "semen" + desc = null + gender = PLURAL + density = 0 + layer = ABOVE_NORMAL_TURF_LAYER + icon = 'icons/obj/genitals/effects.dmi' + icon_state = "semen1" + random_icon_states = list("semen1", "semen2", "semen3", "semen4") + +/obj/effect/decal/cleanable/semen/Initialize(mapload) + . = ..() + dir = GLOB.cardinals + add_blood_DNA(list("Non-human DNA" = "A+")) + +/obj/effect/decal/cleanable/semen/replace_decal(obj/effect/decal/cleanable/semen/S) + if(S.blood_DNA) + blood_DNA |= S.blood_DNA + return ..() + +/datum/reagent/consumable/femcum + name = "Female Ejaculate" + description = "Vaginal lubricant found in most mammals and other animals of similar nature. Where you found this is your own business." + taste_description = "something with a tang" // wew coders who haven't eaten out a girl. + taste_mult = 2 + data = list("donor"=null,"viruses"=null,"donor_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null) + reagent_state = LIQUID + color = "#AAAAAA77" + can_synth = FALSE + nutriment_factor = 0.5 * REAGENTS_METABOLISM + +/obj/effect/decal/cleanable/femcum + name = "female ejaculate" + desc = null + gender = PLURAL + density = 0 + layer = ABOVE_NORMAL_TURF_LAYER + icon = 'icons/obj/genitals/effects.dmi' + icon_state = "fem1" + random_icon_states = list("fem1", "fem2", "fem3", "fem4") + blood_state = null + bloodiness = null + +/obj/effect/decal/cleanable/femcum/Initialize(mapload) + . = ..() + dir = GLOB.cardinals + add_blood_DNA(list("Non-human DNA" = "A+")) + +/obj/effect/decal/cleanable/femcum/replace_decal(obj/effect/decal/cleanable/femcum/F) + if(F.blood_DNA) + blood_DNA |= F.blood_DNA + return ..() + +/datum/reagent/consumable/femcum/reaction_turf(turf/T, reac_volume) + if(!istype(T)) + return + if(reac_volume < 10) + return + + var/obj/effect/decal/cleanable/femcum/S = locate() in T + if(!S) + S = new(T) + if(data["blood_DNA"]) + S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"])) diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm index 67ff61610d..50d94a637e 100644 --- a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm @@ -227,6 +227,18 @@ playsound(M, "sparks", 50, 1) ..() +/datum/reagent/teslium/on_mob_metabolize(mob/living/carbon/human/L) + . = ..() + if(!istype(L)) + return + L.physiology.siemens_coeff *= 2 + +/datum/reagent/teslium/on_mob_end_metabolize(mob/living/carbon/human/L) + . = ..() + if(!istype(L)) + return + L.physiology.siemens_coeff *= 0.5 + /datum/reagent/teslium/energized_jelly name = "Energized Jelly" description = "Electrically-charged jelly. Boosts jellypeople's nervous system, but only shocks other lifeforms." diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 3169d2d3aa..02e4a89e1d 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -675,7 +675,7 @@ /datum/reagent/toxin/lipolicide/on_mob_life(mob/living/carbon/M) if(M.nutrition <= NUTRITION_LEVEL_STARVING) M.adjustToxLoss(1*REM, 0) - M.nutrition = max(M.nutrition - 3, 0) // making the chef more valuable, one meme trap at a time + M.adjust_nutrition(-3) // making the chef more valuable, one meme trap at a time M.overeatduration = 0 return ..() @@ -765,7 +765,9 @@ /datum/reagent/toxin/rotatium/on_mob_life(mob/living/carbon/M) if(M.hud_used) if(current_cycle >= 20 && current_cycle%20 == 0) - var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"]) + var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], + M.hud_used.plane_masters["[LIGHTING_PLANE]"], M.hud_used.plane_masters["[WALL_PLANE]"], + M.hud_used.plane_masters["[ABOVE_WALL_PLANE]"]) var/rotation = min(round(current_cycle/20), 89) // By this point the player is probably puking and quitting anyway for(var/whole_screen in screens) animate(whole_screen, transform = matrix(rotation, MATRIX_ROTATE), time = 5, easing = QUAD_EASING, loop = -1) @@ -793,15 +795,17 @@ /* if(M.hud_used) if(current_cycle >= 5 && current_cycle % 3 == 0) - var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"]) - var/matrix/skew = matrix() + var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], + M.hud_used.plane_masters["[LIGHTING_PLANE]"], M.hud_used.plane_masters["[WALL_PLANE]"], + M.hud_used.plane_masters["[ABOVE_WALL_PLANE]"]) var/matrix/skew = matrix() var/intensity = 8 skew.set_skew(rand(-intensity,intensity), rand(-intensity,intensity)) var/matrix/newmatrix = skew if(prob(33)) // 1/3rd of the time, let's make it stack with the previous matrix! Mwhahahaha! - var/obj/screen/plane_master/PM = M.hud_used.plane_masters["[GAME_PLANE]"] - newmatrix = skew * PM.transform + for(var/whole_screen in screens) + var/obj/screen/plane_master/PM = whole_screen + newmatrix = skew * PM.transform for(var/whole_screen in screens) animate(whole_screen, transform = newmatrix, time = 5, easing = QUAD_EASING, loop = -1) @@ -1015,3 +1019,20 @@ to_chat(M, "[tox_message]") . = 1 ..() + +/datum/reagent/toxin/leadacetate + name = "Lead Acetate" + description = "Used hundreds of years ago as a sweetener, before it was realized that it's incredibly poisonous." + reagent_state = SOLID + color = "#2b2b2b" // rgb: 127, 132, 0 + toxpwr = 0.5 + taste_mult = 1.3 + taste_description = "sugary sweetness" + +/datum/reagent/toxin/leadacetate/on_mob_life(mob/living/carbon/M) + M.adjustOrganLoss(ORGAN_SLOT_EARS,1) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN,1) + if(prob(1)) + to_chat(M, "Ah, what was that? You thought you heard something...") + M.confused += 5 + return ..() diff --git a/code/modules/reagents/chemistry/recipes/drugs.dm b/code/modules/reagents/chemistry/recipes/drugs.dm index 468d29c052..a2b8c27552 100644 --- a/code/modules/reagents/chemistry/recipes/drugs.dm +++ b/code/modules/reagents/chemistry/recipes/drugs.dm @@ -62,3 +62,34 @@ results = list(/datum/reagent/moonsugar = 1, /datum/reagent/medicine/morphine = 2.5) required_temp = 315 //a little above normal body temperature required_reagents = list(/datum/reagent/drug/skooma = 1) +/datum/chemical_reaction/aphro + name = "crocin" + id = /datum/reagent/drug/aphrodisiac + results = list(/datum/reagent/drug/aphrodisiac = 6) + required_reagents = list(/datum/reagent/carbon = 2, /datum/reagent/hydrogen = 2, /datum/reagent/oxygen = 2, /datum/reagent/water = 1) + required_temp = 400 + mix_message = "The mixture boils off a pink vapor..."//The water boils off, leaving the crocin + +/datum/chemical_reaction/aphroplus + name = "hexacrocin" + id = /datum/reagent/drug/aphrodisiacplus + results = list(/datum/reagent/drug/aphrodisiacplus = 1) + required_reagents = list(/datum/reagent/drug/aphrodisiac = 6, /datum/reagent/phenol = 1) + required_temp = 400 + mix_message = "The mixture rapidly condenses and darkens in color..." + +/datum/chemical_reaction/anaphro + name = "camphor" + id = /datum/reagent/drug/anaphrodisiac + results = list(/datum/reagent/drug/anaphrodisiac = 6) + required_reagents = list(/datum/reagent/carbon = 2, /datum/reagent/hydrogen = 2, /datum/reagent/oxygen = 2, /datum/reagent/sulfur = 1) + required_temp = 400 + mix_message = "The mixture boils off a yellow, smelly vapor..."//Sulfur burns off, leaving the camphor + +/datum/chemical_reaction/anaphroplus + name = "pentacamphor" + id = /datum/reagent/drug/anaphrodisiacplus + results = list(/datum/reagent/drug/anaphrodisiacplus = 1) + required_reagents = list(/datum/reagent/drug/aphrodisiac = 5, /datum/reagent/acetone = 1) + required_temp = 300 + mix_message = "The mixture thickens and heats up slighty..." diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm index ce1940994d..df1b57c20b 100644 --- a/code/modules/reagents/chemistry/recipes/others.dm +++ b/code/modules/reagents/chemistry/recipes/others.dm @@ -440,9 +440,8 @@ mob_react = FALSE /datum/chemical_reaction/foam/on_reaction(datum/reagents/holder, multiplier) - var/location = get_turf(holder.my_atom) - for(var/mob/M in viewers(5, location)) - to_chat(M, "The solution spews out foam!") + var/turf/location = get_turf(holder.my_atom) + location.visible_message("The solution spews out foam!") var/datum/effect_system/foam_spread/s = new() s.set_up(multiplier*2, location, holder) s.start() @@ -457,11 +456,8 @@ mob_react = FALSE /datum/chemical_reaction/metalfoam/on_reaction(datum/reagents/holder, multiplier) - var/location = get_turf(holder.my_atom) - - for(var/mob/M in viewers(5, location)) - to_chat(M, "The solution spews out a metallic foam!") - + var/turf/location = get_turf(holder.my_atom) + location.visible_message("The solution spews out a metallic foam!") var/datum/effect_system/foam_spread/metal/s = new() s.set_up(multiplier*5, location, holder, 1) s.start() @@ -488,9 +484,8 @@ mob_react = FALSE /datum/chemical_reaction/ironfoam/on_reaction(datum/reagents/holder, multiplier) - var/location = get_turf(holder.my_atom) - for(var/mob/M in viewers(5, location)) - to_chat(M, "The solution spews out a metallic foam!") + var/turf/location = get_turf(holder.my_atom) + location.visible_message("The solution spews out metallic foam!") var/datum/effect_system/foam_spread/metal/s = new() s.set_up(multiplier*5, location, holder, 2) s.start() @@ -636,6 +631,11 @@ results = list(/datum/reagent/concentrated_barbers_aid = 2) required_reagents = list(/datum/reagent/barbers_aid = 1, /datum/reagent/toxin/mutagen = 1) +/datum/chemical_reaction/baldium + results = list(/datum/reagent/baldium = 1) + required_reagents = list(/datum/reagent/radium = 1, /datum/reagent/toxin/acid = 1, /datum/reagent/lye = 1) + required_temp = 395 + /datum/chemical_reaction/saltpetre name = "saltpetre" id = /datum/reagent/saltpetre diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm index 8782d65f76..1d06aaacde 100644 --- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm +++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm @@ -429,7 +429,7 @@ noexplosion = TRUE mix_message = "The teslium starts to spark as electricity arcs away from it!" mix_sound = 'sound/machines/defib_zap.ogg' - var/tesla_flags = TESLA_MOB_DAMAGE | TESLA_OBJ_DAMAGE | TESLA_MOB_STUN + var/zap_flags = ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE | ZAP_MOB_STUN /datum/chemical_reaction/reagent_explosion/teslium_lightning/on_reaction(datum/reagents/holder, multiplier) var/T1 = multiplier * 20 //100 units : Zap 3 times, with powers 2000/5000/12000. Tesla revolvers have a power of 10000 for comparison. @@ -437,15 +437,15 @@ var/T3 = multiplier * 120 sleep(5) if(multiplier >= 75) - tesla_zap(holder.my_atom, 7, T1, tesla_flags) + tesla_zap(holder.my_atom, 7, T1, zap_flags) playsound(holder.my_atom, 'sound/machines/defib_zap.ogg', 50, 1) sleep(15) if(multiplier >= 40) - tesla_zap(holder.my_atom, 7, T2, tesla_flags) + tesla_zap(holder.my_atom, 7, T2, zap_flags) playsound(holder.my_atom, 'sound/machines/defib_zap.ogg', 50, 1) sleep(15) if(multiplier >= 10) //10 units minimum for lightning, 40 units for secondary blast, 75 units for tertiary blast. - tesla_zap(holder.my_atom, 7, T3, tesla_flags) + tesla_zap(holder.my_atom, 7, T3, zap_flags) playsound(holder.my_atom, 'sound/machines/defib_zap.ogg', 50, 1) ..() diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index f326b94e44..fbdbb5f656 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -160,11 +160,8 @@ /obj/item/reagent_containers/microwave_act(obj/machinery/microwave/M) reagents.expose_temperature(1000) if(container_flags & TEMP_WEAK) - var/list/seen = viewers(5, get_turf(src)) - var/iconhtml = icon2html(src, seen) - for(var/mob/H in seen) - to_chat(H, "[iconhtml] \The [src]'s melts from the temperature!") - playsound(get_turf(src), 'sound/FermiChem/heatmelt.ogg', 80, 1) + visible_message("[icon2html(src, viewers(DEFAULT_MESSAGE_RANGE, src))] [src]'s melts from the temperature!") + playsound(src, 'sound/FermiChem/heatmelt.ogg', 80, 1) qdel(src) ..() @@ -184,7 +181,7 @@ if((reagents.pH < 1.5) || (reagents.pH > 12.5)) START_PROCESSING(SSobj, src) else if((reagents.pH < -3) || (reagents.pH > 17)) - visible_message("[icon2html(src, viewers(src))] \The [src] is damaged by the super pH and begins to deform!") + visible_message("[icon2html(src, viewers(DEFAULT_MESSAGE_RANGE, src))] \The [src] is damaged by the super pH and begins to deform!") reagents.pH = clamp(reagents.pH, -3, 17) container_HP -= 1 @@ -221,15 +218,11 @@ container_HP -= damage - var/list/seen = viewers(5, get_turf(src)) - var/iconhtml = icon2html(src, seen) - var/damage_percent = ((container_HP / initial(container_HP)*100)) switch(damage_percent) if(-INFINITY to 0) - for(var/mob/M in seen) - to_chat(M, "[iconhtml] \The [src]'s melts [cause]!") - playsound(get_turf(src), 'sound/FermiChem/acidmelt.ogg', 80, 1) + visible_message("[icon2html(src, viewers(DEFAULT_MESSAGE_RANGE, src))] [src]'s melts [cause]!") + playsound(src, 'sound/FermiChem/acidmelt.ogg', 80, 1) SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times beakers have melted") STOP_PROCESSING(SSobj, src) qdel(src) @@ -246,5 +239,4 @@ update_icon() if(prob(25)) - for(var/mob/M in seen) - to_chat(M, "[iconhtml] \The [src]'s is damaged by [cause] and begins to deform!") + visible_message("[icon2html(src, viewers(DEFAULT_MESSAGE_RANGE, src))] [src]'s is damaged by [cause] and begins to deform!") diff --git a/code/modules/reagents/reagent_containers/dropper.dm b/code/modules/reagents/reagent_containers/dropper.dm index 846637850b..b4c570dfc6 100644 --- a/code/modules/reagents/reagent_containers/dropper.dm +++ b/code/modules/reagents/reagent_containers/dropper.dm @@ -7,6 +7,7 @@ possible_transfer_amounts = list(1, 2, 3, 4, 5) volume = 5 reagent_flags = TRANSPARENT + custom_price = 75 /obj/item/reagent_containers/dropper/afterattack(obj/target, mob/user , proximity) . = ..() diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index 368f476183..b4e954f147 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -361,6 +361,7 @@ icon = 'icons/obj/drinks.dmi' icon_state = "smallbottle" item_state = "bottle" + custom_price = 30 list_reagents = list(/datum/reagent/water = 49.5, /datum/reagent/fluorine = 0.5)//see desc, don't think about it too hard custom_materials = list(/datum/material/glass=0) volume = 50 diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index b24e6ab733..99a93e58dc 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -96,6 +96,8 @@ reagent_flags = DRAWABLE flags_1 = null list_reagents = list(/datum/reagent/medicine/epinephrine = 10, /datum/reagent/preservahyde = 3) + custom_price = 150 + custom_premium_price = 300 /obj/item/reagent_containers/hypospray/medipen/suicide_act(mob/living/carbon/user) user.visible_message("[user] begins to choke on \the [src]! It looks like [user.p_theyre()] trying to commit suicide!") diff --git a/code/modules/reagents/reagent_containers/maunamug.dm b/code/modules/reagents/reagent_containers/maunamug.dm new file mode 100644 index 0000000000..18e6cfa847 --- /dev/null +++ b/code/modules/reagents/reagent_containers/maunamug.dm @@ -0,0 +1,117 @@ +/obj/item/reagent_containers/glass/maunamug + name = "mauna mug" + desc = "A drink served in a classy mug. Now with built-in heating!" + icon = 'icons/obj/mauna_mug.dmi' + icon_state = "maunamug" + spillable = TRUE + reagent_flags = OPENCONTAINER +// fill_icon_state = "maunafilling" +// fill_icon_thresholds = list(25) + var/obj/item/stock_parts/cell/cell + var/open = FALSE + var/on = FALSE + +/obj/item/reagent_containers/glass/maunamug/Initialize(mapload, vol) + . = ..() + cell = new /obj/item/stock_parts/cell(src) + +/obj/item/reagent_containers/glass/maunamug/examine(mob/user) + . = ..() + . += "The status display reads: Current temperature: [reagents.chem_temp]K Current Charge:[cell ? "[cell.charge / cell.maxcharge * 100]%" : "No cell found"]." + if(open) + . += "The battery case is open." + +/obj/item/reagent_containers/glass/maunamug/update_overlays() + . = ..() + if(reagents.total_volume >= 25) + . += mutable_appearance('icons/obj/reagentfillings.dmi', "maunafilling25", color = mix_color_from_reagents(reagents.reagent_list)) + +/obj/item/reagent_containers/glass/maunamug/process() + ..() + if(on && (!cell || cell.charge <= 0)) //Check if we ran out of power + change_power_status(FALSE) + return FALSE + cell.use(10) //Basic cell goes for like 200 seconds, bluespace for 8000 + if(!reagents.total_volume) + return FALSE + var/max_temp = min(500 + (500 * (0.2 * cell.rating)), 1000) // 373 to 1000 + reagents.adjust_thermal_energy(0.8 * cell.maxcharge * reagents.total_volume, max_temp = max_temp) // 4 kelvin every tick on a basic cell. 160k on bluespace + reagents.handle_reactions() + update_icon() + if(reagents.chem_temp >= max_temp) + change_power_status(FALSE) + audible_message("The Mauna Mug lets out a happy beep and turns off!") + playsound(src, 'sound/machines/chime.ogg', 50) + +/obj/item/reagent_containers/glass/maunamug/Destroy() + if(cell) + QDEL_NULL(cell) + STOP_PROCESSING(SSobj, src) + . = ..() + + +/obj/item/reagent_containers/glass/maunamug/attack_self(mob/user) + if(on) + change_power_status(FALSE) + else + if(!cell || cell.charge <= 0) + return FALSE //No power, so don't turn on + change_power_status(TRUE) + +/obj/item/reagent_containers/glass/maunamug/proc/change_power_status(status) + on = status + if(on) + START_PROCESSING(SSobj, src) + else + STOP_PROCESSING(SSobj, src) + update_icon() + +/obj/item/reagent_containers/glass/maunamug/screwdriver_act(mob/living/user, obj/item/I) + . = ..() + open = !open + to_chat(user, "You screw the battery case on [src] [open ? "open" : "closed"] .") + update_icon() + +/obj/item/reagent_containers/glass/maunamug/attackby(obj/item/I, mob/user, params) + add_fingerprint(user) + if(!istype(I, /obj/item/stock_parts/cell)) + return ..() + if(!open) + to_chat(user, "The battery case must be open to insert a power cell!") + return FALSE + if(cell) + to_chat(user, "There is already a power cell inside!") + return FALSE + else if(!user.transferItemToLoc(I, src)) + return + cell = I + user.visible_message("[user] inserts a power cell into [src].", "You insert the power cell into [src].") + update_icon() + +/obj/item/reagent_containers/glass/maunamug/attack_hand(mob/living/user) + if(cell && open) + cell.update_icon() + user.put_in_hands(cell) + cell = null + to_chat(user, "You remove the power cell from [src].") + on = FALSE + update_icon() + return TRUE + return ..() + +/obj/item/reagent_containers/glass/maunamug/update_icon() + ..() + if(open) + if(cell) + icon_state = "maunamug_bat" + else + icon_state = "maunamug_no_bat" + else if(on) + icon_state = "maunamug_on" + else + icon_state = "maunamug" + if(reagents.total_volume && reagents.chem_temp >= 400) + var/intensity = (reagents.chem_temp - 400) * 1 / 600 //Get the opacity of the incandescent overlay. Ranging from 400 to 1000 + var/mutable_appearance/mug_glow = mutable_appearance(icon, "maunamug_incand") + mug_glow.alpha = 255 * intensity + add_overlay(mug_glow) diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index e6fa18ba9c..1247a7abc3 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -22,10 +22,17 @@ if(reagents.total_volume && roundstart) name += " ([reagents.total_volume]u)" - /obj/item/reagent_containers/pill/attack_self(mob/user) return +/obj/item/reagent_containers/pill/get_w_volume() + switch(reagents.total_volume) + if(0 to 9.5) + return 1 + if(9.5 to 25) + return DEFAULT_VOLUME_TINY + else + return DEFAULT_VOLUME_SMALL /obj/item/reagent_containers/pill/attack(mob/M, mob/user, def_zone) if(!canconsume(M, user)) @@ -72,9 +79,8 @@ to_chat(user, "[target] is full.") return - to_chat(user, "You dissolve [src] in [target].") - for(var/mob/O in viewers(2, user)) //viewers is necessary here because of the small radius - to_chat(O, "[user] slips something into [target]!") + user.visible_message("[user] slips something into [target]!", + "You dissolve [src] in [target].", vision_distance = 2) reagents.trans_to(target, reagents.total_volume) qdel(src) @@ -138,14 +144,14 @@ name = "mannitol pill" desc = "Used to treat brain damage." icon_state = "pill17" - list_reagents = list(/datum/reagent/medicine/mannitol = 50) + list_reagents = list(/datum/reagent/medicine/mannitol = 25) roundstart = 1 /obj/item/reagent_containers/pill/mutadone name = "mutadone pill" desc = "Used to treat genetic damage." icon_state = "pill20" - list_reagents = list(/datum/reagent/medicine/mutadone = 50) + list_reagents = list(/datum/reagent/medicine/mutadone = 25) roundstart = 1 /obj/item/reagent_containers/pill/salicyclic @@ -187,14 +193,14 @@ name = "prussian blue pill" desc = "Used to treat heavy radition poisoning." icon_state = "prussian_blue" - list_reagents = list(/datum/reagent/medicine/prussian_blue = 25, /datum/reagent/water = 10) + list_reagents = list(/datum/reagent/medicine/prussian_blue = 25) roundstart = 1 /obj/item/reagent_containers/pill/mutarad name = "radiation treatment deluxe pill" desc = "Used to treat heavy radition poisoning and genetic defects." icon_state = "anit_rad_fixgene" - list_reagents = list(/datum/reagent/medicine/prussian_blue = 15, /datum/reagent/medicine/potass_iodide = 15, /datum/reagent/medicine/mutadone = 15, /datum/reagent/water = 5) + list_reagents = list(/datum/reagent/medicine/prussian_blue = 10, /datum/reagent/medicine/potass_iodide = 10, /datum/reagent/medicine/mutadone = 5) roundstart = 1 ///////////////////////////////////////// this pill is used only in a legion mob drop @@ -217,7 +223,7 @@ /obj/item/reagent_containers/pill/lsd name = "hallucinogen pill" - list_reagents = list(/datum/reagent/drug/mushroomhallucinogen = 15, /datum/reagent/toxin/mindbreaker = 15) + list_reagents = list(/datum/reagent/drug/mushroomhallucinogen = 12.5, /datum/reagent/toxin/mindbreaker = 12.5) /obj/item/reagent_containers/pill/aranesp diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 1a2742d2a6..4782a80c62 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -15,6 +15,7 @@ var/show_filling = TRUE custom_materials = list(/datum/material/iron=10, /datum/material/glass=20) reagent_flags = TRANSPARENT + custom_price = 100 /obj/item/reagent_containers/syringe/Initialize() . = ..() diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index 1e687816ff..bc4e214161 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -120,9 +120,10 @@ /obj/structure/reagent_dispensers/fueltank/fire_act(exposed_temperature, exposed_volume) boom() -/obj/structure/reagent_dispensers/fueltank/tesla_act() +/obj/structure/reagent_dispensers/fueltank/zap_act(power, zap_flags, shocked_objects) ..() //extend the zap - boom() + if(ZAP_OBJ_DAMAGE & zap_flags) + boom() /obj/structure/reagent_dispensers/fueltank/bullet_act(obj/item/projectile/P) . = ..() @@ -169,6 +170,7 @@ name = "pepper spray refiller" desc = "Contains condensed capsaicin for use in law \"enforcement.\"" icon_state = "pepper" + plane = ABOVE_WALL_PLANE anchored = TRUE density = FALSE reagent_id = /datum/reagent/consumable/condensedcapsaicin @@ -182,6 +184,7 @@ name = "virus food dispenser" desc = "A dispenser of low-potency virus mutagenic." icon_state = "virus_food" + plane = ABOVE_WALL_PLANE anchored = TRUE density = FALSE reagent_id = /datum/reagent/consumable/virus_food @@ -211,7 +214,6 @@ /obj/structure/reagent_dispensers/keg name = "keg" desc = "A keg." - icon = 'modular_citadel/icons/obj/objects.dmi' icon_state = "keg" /obj/structure/reagent_dispensers/keg/mead @@ -239,12 +241,6 @@ icon_state = "whitekeg" reagent_id = /datum/reagent/consumable/milk -/obj/structure/reagent_dispensers/keg/semen - name = "keg of semen" - desc = "Dear lord, where did this even come from?" - icon_state = "whitekeg" - reagent_id = /datum/reagent/consumable/semen - /obj/structure/reagent_dispensers/keg/gargle name = "keg of pan galactic gargleblaster" desc = "A keg of... wow that's a long name." diff --git a/code/modules/recycling/disposal/pipe.dm b/code/modules/recycling/disposal/pipe.dm index aed2310a7f..45d3d9da25 100644 --- a/code/modules/recycling/disposal/pipe.dm +++ b/code/modules/recycling/disposal/pipe.dm @@ -14,6 +14,7 @@ max_integrity = 200 armor = list("melee" = 25, "bullet" = 10, "laser" = 10, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30) layer = DISPOSAL_PIPE_LAYER // slightly lower than wires and other pipes + plane = ABOVE_WALL_PLANE rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE var/dpdir = NONE // bitmask of pipe directions var/initialize_dirs = NONE // bitflags of pipe directions added on init, see \code\_DEFINES\pipe_construction.dm diff --git a/code/modules/research/bepis.dm b/code/modules/research/bepis.dm new file mode 100644 index 0000000000..c6ce45f160 --- /dev/null +++ b/code/modules/research/bepis.dm @@ -0,0 +1,270 @@ +//This system is designed to act as an in-between for cargo and science, and the first major money sink in the game outside of just buying things from cargo (As of 10/9/19, anyway). + +//economics defined values, subject to change should anything be too high or low in practice. + +#define MACHINE_OPERATION 100000 +#define MACHINE_OVERLOAD 500000 +#define MAJOR_THRESHOLD 5500 +#define MINOR_THRESHOLD 3500 +#define STANDARD_DEVIATION 1000 + +/obj/machinery/rnd/bepis + name = "\improper B.E.P.I.S. Chamber" + desc = "A high fidelity testing device which unlocks the secrets of the known universe using the two most powerful substances available to man: excessive amounts of electricity and capital." + icon = 'icons/obj/machines/bepis.dmi' + icon_state = "chamber" + density = TRUE + layer = ABOVE_MOB_LAYER + use_power = IDLE_POWER_USE + active_power_usage = 1500 + circuit = /obj/item/circuitboard/machine/bepis + + var/banking_amount = 100 + var/banked_cash = 0 //stored player cash + var/datum/bank_account/account //payer's account. + var/account_name //name of the payer's account. + var/error_cause = null + //Vars related to probability and chance of success for testing + var/major_threshold = MAJOR_THRESHOLD + var/minor_threshold = MINOR_THRESHOLD + var/std = STANDARD_DEVIATION //That's Standard Deviation, what did you think it was? + //Stock part variables + var/power_saver = 1 + var/inaccuracy_percentage = 1.5 + var/positive_cash_offset = 0 + var/negative_cash_offset = 0 + var/minor_rewards = list(/obj/item/stack/circuit_stack/full, //To add a new minor reward, add it here. + /obj/item/airlock_painter/decal, + /obj/item/pen/survival, + /obj/item/circuitboard/machine/sleeper/party, + /obj/item/toy/sprayoncan) + var/static/list/item_list = list() + +/obj/machinery/rnd/bepis/attackby(obj/item/O, mob/user, params) + if(default_deconstruction_screwdriver(user, "chamber_open", "chamber", O)) + update_icon_state() + return + if(default_deconstruction_crowbar(O)) + return + if(!is_operational()) + to_chat(user, "[src] can't accept money when it's not functioning.") + return + if(istype(O, /obj/item/holochip) || istype(O, /obj/item/stack/spacecash)) + var/deposit_value = O.get_item_credit_value() + banked_cash += deposit_value + qdel(O) + say("Deposited [deposit_value] credits into storage.") + update_icon_state() + return + if(istype(O, /obj/item/card/id)) + var/obj/item/card/id/Card = O + if(Card.registered_account) + account = Card.registered_account + account_name = Card.registered_name + say("New account detected. Console Updated.") + else + say("No account detected on card. Aborting.") + return + return ..() + +/obj/machinery/rnd/bepis/RefreshParts() + var/C = 0 + var/M = 0 + var/L = 0 + var/S = 0 + for(var/obj/item/stock_parts/capacitor/Cap in component_parts) + C += ((Cap.rating - 1) * 0.1) + power_saver = 1 - C + for(var/obj/item/stock_parts/manipulator/Manip in component_parts) + M += ((Manip.rating - 1) * 250) + positive_cash_offset = M + for(var/obj/item/stock_parts/micro_laser/Laser in component_parts) + L += ((Laser.rating - 1) * 250) + negative_cash_offset = L + for(var/obj/item/stock_parts/scanning_module/Scan in component_parts) + S += ((Scan.rating - 1) * 0.25) + inaccuracy_percentage = (1.5 - S) + +/obj/machinery/rnd/bepis/proc/depositcash() + var/deposit_value = 0 + deposit_value = banking_amount + if(deposit_value == 0) + update_icon_state() + say("Attempting to deposit 0 credits. Aborting.") + return + deposit_value = clamp(round(deposit_value, 1), 1, 15000) + if(!account) + say("Cannot find user account. Please swipe a valid ID.") + return + if(!account.has_money(deposit_value)) + say("You do not possess enough credits.") + return + account.adjust_money(-deposit_value) //The money vanishes, not paid to any accounts. + SSblackbox.record_feedback("amount", "BEPIS_credits_spent", deposit_value) + banked_cash += deposit_value + use_power(1000 * power_saver) + say("Cash deposit successful. There is [banked_cash] in the chamber.") + update_icon_state() + return + +/obj/machinery/rnd/bepis/proc/withdrawcash() + var/withdraw_value = 0 + withdraw_value = banking_amount + if(withdraw_value > banked_cash) + say("Cannot withdraw more than stored funds. Aborting.") + else + banked_cash -= withdraw_value + new /obj/item/holochip(src.loc, withdraw_value) + say("Withdrawing [withdraw_value] credits from the chamber.") + update_icon_state() + return + +/obj/machinery/rnd/bepis/proc/calcsuccess() + var/turf/dropturf = null + var/gauss_major = 0 + var/gauss_minor = 0 + var/gauss_real = 0 + var/list/turfs = block(locate(x-1,y-1,z),locate(x+1,y+1,z)) //NO MORE DISCS IN WINDOWS + while(length(turfs)) + var/turf/T = pick_n_take(turfs) + if(is_blocked_turf(T, exclude_mobs=TRUE)) + continue + else + dropturf = T + break + if (!dropturf) + dropturf = drop_location() + gauss_major = (gaussian(major_threshold, std) - negative_cash_offset) //This is the randomized profit value that this experiment has to surpass to unlock a tech. + gauss_minor = (gaussian(minor_threshold, std) - negative_cash_offset) //And this is the threshold to instead get a minor prize. + gauss_real = (gaussian(banked_cash, std*inaccuracy_percentage) + positive_cash_offset) //this is the randomized profit value that your experiment expects to give. + say("Real: [gauss_real]. Minor: [gauss_minor]. Major: [gauss_major].") + flick("chamber_flash",src) + update_icon_state() + banked_cash = 0 + if((gauss_real >= gauss_major) && (SSresearch.techweb_nodes_experimental.len > 0)) //Major Success. + say("Experiment concluded with major success. New technology node discovered on technology disc.") + new /obj/item/disk/tech_disk/major(dropturf,1) + if(SSresearch.techweb_nodes_experimental.len == 0) + say("Expended all available experimental technology nodes. Resorting to minor rewards.") + return + if(gauss_real >= gauss_minor) //Minor Success. + var/reward = pick(minor_rewards) + new reward(dropturf) + say("Experiment concluded with partial success. Dispensing compiled research efforts.") + return + if(gauss_real <= -1) //Critical Failure + say("ERROR: CRITICAL MACHIME MALFUNCTI- ON. CURRENCY IS NOT CRASH. CANNOT COMPUTE COMMAND: 'make bucks'") //not a typo, for once. + new /mob/living/simple_animal/deer(dropturf, 1) + use_power(MACHINE_OVERLOAD * power_saver) //To prevent gambling at low cost and also prevent spamming for infinite deer. + return + //Minor Failure + error_cause = pick("attempted to sell grey products to American dominated market.","attempted to sell gray products to British dominated market.","placed wild assumption that PDAs would go out of style.","simulated product #76 damaged brand reputation mortally.","simulated business model resembled 'pyramid scheme' by 98.7%.","product accidently granted override access to all station doors.") + say("Experiment concluded with zero product viability. Cause of error: [error_cause]") + return + +/obj/machinery/rnd/bepis/update_icon_state() + if(panel_open == TRUE) + icon_state = "chamber_open" + return + if((use_power == ACTIVE_POWER_USE) && (banked_cash > 0) && (is_operational())) + icon_state = "chamber_active_loaded" + return + if (((use_power == IDLE_POWER_USE) && (banked_cash > 0)) || (banked_cash > 0) && (!is_operational())) + icon_state = "chamber_loaded" + return + if(use_power == ACTIVE_POWER_USE && is_operational()) + icon_state = "chamber_active" + return + if(((use_power == IDLE_POWER_USE) && (banked_cash == 0)) || (!is_operational())) + icon_state = "chamber" + return + +/obj/machinery/rnd/bepis/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "bepis", name, 500, 480, master_ui, state) + ui.open() + RefreshParts() + +/obj/machinery/rnd/bepis/ui_data(mob/user) + var/list/data = list() + var/powered = FALSE + var/zvalue = (banked_cash - (major_threshold - positive_cash_offset - negative_cash_offset))/(std) + var/std_success = 0 + var/prob_success = 0 + //Admittedly this is messy, but not nearly as messy as the alternative, which is jury-rigging an entire Z-table into the code, or making an adaptive z-table. + var/z = abs(zvalue) + if(z > 0 && z <= 0.5) + std_success = 19.1 + else if(z > 0.5 && z <= 1.0) + std_success = 34.1 + else if(z > 1.0 && z <= 1.5) + std_success = 43.3 + else if(z > 1.5 && z <= 2.0) + std_success = 47.7 + else if(z > 2.0 && z <= 2.5) + std_success = 49.4 + else + std_success = 50 + if(zvalue > 0) + prob_success = 50 + std_success + else if(zvalue == 0) + prob_success = 50 + else + prob_success = 50 - std_success + + if(use_power == ACTIVE_POWER_USE) + powered = TRUE + data["account_owner"] = account_name + data["amount"] = banking_amount + data["stored_cash"] = banked_cash + data["mean_value"] = (major_threshold - positive_cash_offset - negative_cash_offset) + data["error_name"] = error_cause + data["power_saver"] = power_saver + data["accuracy_percentage"] = inaccuracy_percentage * 100 + data["positive_cash_offset"] = positive_cash_offset + data["negative_cash_offset"] = negative_cash_offset + data["manual_power"] = powered ? FALSE : TRUE + data["silicon_check"] = issilicon(user) + data["success_estimate"] = prob_success + return data + +/obj/machinery/rnd/bepis/ui_act(action,params) + if(..()) + return + switch(action) + if("deposit_cash") + if(use_power == IDLE_POWER_USE) + return + depositcash() + if("withdraw_cash") + if(use_power == IDLE_POWER_USE) + return + withdrawcash() + if("begin_experiment") + if(use_power == IDLE_POWER_USE) + return + if(banked_cash == 0) + say("Please deposit funds to begin testing.") + return + calcsuccess() + use_power(MACHINE_OPERATION * power_saver) //This thing should eat your APC battery if you're not careful. + use_power = IDLE_POWER_USE //Machine shuts off after use to prevent spam and look better visually. + update_icon_state() + if("amount") + var/input = text2num(params["amount"]) + if(input) + banking_amount = input + if("toggle_power") + if(use_power == ACTIVE_POWER_USE) + use_power = IDLE_POWER_USE + else + use_power = ACTIVE_POWER_USE + update_icon_state() + if("account_reset") + if(use_power == IDLE_POWER_USE) + return + account_name = "" + account = null + say("Account settings reset.") + . = TRUE diff --git a/code/modules/research/designs/autobotter_designs.dm b/code/modules/research/designs/autobotter_designs.dm index eab7423b91..c2ff7c953b 100644 --- a/code/modules/research/designs/autobotter_designs.dm +++ b/code/modules/research/designs/autobotter_designs.dm @@ -14,7 +14,7 @@ /datum/design/bottle materials = list(/datum/material/glass = 1200) build_type = AUTOBOTTLER - category = list("Storge") + category = list("Storage") /datum/design/bottle/wine name = "Bottle Design (Wine)" @@ -331,4 +331,4 @@ id = "greenroad" reagents_list = list(/datum/reagent/consumable/vitfro = 50, /datum/reagent/consumable/ethanol/rum = 30, /datum/reagent/ash = 10) category = list("Beers") - build_path = /obj/item/export/bottle/greenroad \ No newline at end of file + build_path = /obj/item/export/bottle/greenroad diff --git a/code/modules/research/designs/autolathe_desings/autolathe_designs_construction.dm b/code/modules/research/designs/autolathe_desings/autolathe_designs_construction.dm index ee9ee14e4a..f8cf5c1d84 100644 --- a/code/modules/research/designs/autolathe_desings/autolathe_designs_construction.dm +++ b/code/modules/research/designs/autolathe_desings/autolathe_designs_construction.dm @@ -112,8 +112,8 @@ /datum/design/rcd_ammo_large name = "Large Compressed Matter Cartridge" id = "rcd_ammo_large" - build_type = AUTOLATHE | PROTOLATHE + build_type = AUTOLATHE | PROTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 48000, /datum/material/glass = 32000) build_path = /obj/item/rcd_ammo/large - category = list("Tool Designs") + category = list("hacked", "Construction", "Tool Designs") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING diff --git a/code/modules/research/designs/autolathe_desings/autolathe_designs_electronics.dm b/code/modules/research/designs/autolathe_desings/autolathe_designs_electronics.dm index 5d80b91087..78b0a365c5 100644 --- a/code/modules/research/designs/autolathe_desings/autolathe_designs_electronics.dm +++ b/code/modules/research/designs/autolathe_desings/autolathe_designs_electronics.dm @@ -82,3 +82,11 @@ materials = list(/datum/material/iron = 100, /datum/material/glass = 100) build_path = /obj/item/assembly/control/electrochromatic category = list("initial", "Electronics") + +/datum/design/electrochromatic_kit + name = "Electrochromatic Upgrade Kit" + id = "electrochromatic_kit" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 2010, /datum/material/glass = 5) + build_path = /obj/item/electronics/electrochromatic_kit + category = list("initial", "Electronics") diff --git a/code/modules/research/designs/autolathe_desings/autolathe_designs_medical_and_dinnerware.dm b/code/modules/research/designs/autolathe_desings/autolathe_designs_medical_and_dinnerware.dm index b62f30e041..76ec6224b8 100644 --- a/code/modules/research/designs/autolathe_desings/autolathe_designs_medical_and_dinnerware.dm +++ b/code/modules/research/designs/autolathe_desings/autolathe_designs_medical_and_dinnerware.dm @@ -8,7 +8,7 @@ /datum/design/kitchen_knife name = "Kitchen Knife" id = "kitchen_knife" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 12000) build_path = /obj/item/kitchen/knife category = list("initial","Dinnerware") @@ -140,7 +140,7 @@ /datum/design/healthanalyzer name = "Health Analyzer" id = "healthanalyzer" - build_type = AUTOLATHE | PROTOLATHE + build_type = AUTOLATHE | PROTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 500, /datum/material/glass = 50) build_path = /obj/item/healthanalyzer category = list("initial", "Medical") diff --git a/code/modules/research/designs/autolathe_desings/autolathe_designs_sec_and_hacked.dm b/code/modules/research/designs/autolathe_desings/autolathe_designs_sec_and_hacked.dm index 173240e196..20a5370793 100644 --- a/code/modules/research/designs/autolathe_desings/autolathe_designs_sec_and_hacked.dm +++ b/code/modules/research/designs/autolathe_desings/autolathe_designs_sec_and_hacked.dm @@ -36,7 +36,7 @@ /datum/design/large_welding_tool name = "Industrial Welding Tool" id = "large_welding_tool" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 70, /datum/material/glass = 60) build_path = /obj/item/weldingtool/largetank category = list("hacked", "Tools") @@ -44,7 +44,7 @@ /datum/design/flamethrower name = "Flamethrower" id = "flamethrower" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 500) build_path = /obj/item/flamethrower/full category = list("hacked", "Security") @@ -52,7 +52,7 @@ /datum/design/rcd name = "Rapid Construction Device (RCD)" id = "rcd" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 30000) build_path = /obj/item/construction/rcd category = list("hacked", "Construction") @@ -60,7 +60,7 @@ /datum/design/rpd name = "Rapid Pipe Dispenser (RPD)" id = "rpd" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 75000, /datum/material/glass = 37500) build_path = /obj/item/pipe_dispenser category = list("hacked", "Construction") @@ -68,7 +68,7 @@ /datum/design/handcuffs name = "Handcuffs" id = "handcuffs" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 500) build_path = /obj/item/restraints/handcuffs category = list("hacked", "Security") @@ -76,7 +76,7 @@ /datum/design/receiver name = "Modular Receiver" id = "receiver" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 15000) build_path = /obj/item/weaponcrafting/receiver category = list("hacked", "Security") @@ -84,7 +84,7 @@ /datum/design/shotgun_slug name = "Shotgun Slug" id = "shotgun_slug" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 4000) build_path = /obj/item/ammo_casing/shotgun category = list("hacked", "Security") @@ -92,7 +92,7 @@ /datum/design/buckshot_shell name = "Buckshot Shell" id = "buckshot_shell" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 4000) build_path = /obj/item/ammo_casing/shotgun/buckshot category = list("hacked", "Security") @@ -100,7 +100,7 @@ /datum/design/shotgun_dart name = "Shotgun Dart" id = "shotgun_dart" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 4000) build_path = /obj/item/ammo_casing/shotgun/dart category = list("hacked", "Security") @@ -108,7 +108,7 @@ /datum/design/incendiary_slug name = "Incendiary Slug" id = "incendiary_slug" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 4000) build_path = /obj/item/ammo_casing/shotgun/incendiary category = list("hacked", "Security") @@ -116,7 +116,7 @@ /datum/design/riot_dart name = "Foam Riot Dart" id = "riot_dart" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 1125) //Discount for making individually - no box = less metal! build_path = /obj/item/ammo_casing/caseless/foam_dart/riot category = list("hacked", "Security") @@ -124,7 +124,7 @@ /datum/design/riot_darts name = "Foam Riot Dart Box" id = "riot_darts" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 50000) //Comes with 40 darts build_path = /obj/item/ammo_box/foambox/riot category = list("hacked", "Security") @@ -132,7 +132,7 @@ /datum/design/a357 name = "Revolver Bullet (.357)" id = "a357" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 4000) build_path = /obj/item/ammo_casing/a357 category = list("hacked", "Security") @@ -140,7 +140,7 @@ /datum/design/a762 name = "Rifle Bullet (7.62mm)" id = "a762" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 5000) //need seclathe for clips build_path = /obj/item/ammo_casing/a762 category = list("hacked", "Security") @@ -148,7 +148,7 @@ /datum/design/c10mm name = "Ammo Box (10mm)" id = "c10mm" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 30000) build_path = /obj/item/ammo_box/c10mm category = list("hacked", "Security") @@ -156,7 +156,7 @@ /datum/design/c45 name = "Ammo Box (.45)" id = "c45" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 30000) build_path = /obj/item/ammo_box/c45 category = list("hacked", "Security") @@ -164,7 +164,7 @@ /datum/design/c9mm name = "Ammo Box (9mm)" id = "c9mm" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 30000) build_path = /obj/item/ammo_box/c9mm category = list("hacked", "Security") @@ -172,7 +172,7 @@ /datum/design/electropack name = "Electropack" id = "electropack" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 10000, /datum/material/glass = 2500) build_path = /obj/item/electropack category = list("hacked", "Security") @@ -180,7 +180,7 @@ /datum/design/cleaver name = "Butcher's Cleaver" id = "cleaver" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 18000) build_path = /obj/item/kitchen/knife/butcher category = list("hacked", "Dinnerware") diff --git a/code/modules/research/designs/autolathe_desings/autolathe_designs_tcomms_and_misc.dm b/code/modules/research/designs/autolathe_desings/autolathe_designs_tcomms_and_misc.dm index 30cd56c66a..eebeec2c78 100644 --- a/code/modules/research/designs/autolathe_desings/autolathe_designs_tcomms_and_misc.dm +++ b/code/modules/research/designs/autolathe_desings/autolathe_designs_tcomms_and_misc.dm @@ -256,3 +256,19 @@ materials = list(/datum/material/iron = 300, /datum/material/glass = 150) build_path = /obj/item/key/collar category = list("initial", "Misc") + +/datum/design/price_tagger + name = "Price Tagger" + id = "price_tagger" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 1500, /datum/material/glass = 500) + build_path = /obj/item/price_tagger + category = list("initial", "Misc") + +/datum/design/custom_vendor_refill + name = "Custom Vendor Refill" + id = "custom_vendor_refill" + build_type = AUTOLATHE + materials = list(/datum/material/iron = 5000, /datum/material/glass = 2000) + build_path = /obj/item/vending_refill/custom + category = list("initial", "Misc") \ No newline at end of file diff --git a/code/modules/research/designs/autolathe_desings/autolathe_designs_tools.dm b/code/modules/research/designs/autolathe_desings/autolathe_designs_tools.dm index 8288ceff23..330dfb8f8a 100644 --- a/code/modules/research/designs/autolathe_desings/autolathe_designs_tools.dm +++ b/code/modules/research/designs/autolathe_desings/autolathe_designs_tools.dm @@ -49,7 +49,7 @@ /datum/design/multitool name = "Multitool" id = "multitool" - build_type = AUTOLATHE | PROTOLATHE + build_type = AUTOLATHE | PROTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 50, /datum/material/glass = 20) build_path = /obj/item/multitool category = list("initial","Tools","Tool Designs") @@ -75,7 +75,7 @@ /datum/design/weldingtool name = "Welding Tool" id = "welding_tool" - build_type = AUTOLATHE + build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 70, /datum/material/glass = 20) build_path = /obj/item/weldingtool category = list("initial","Tools","Tool Designs") @@ -97,6 +97,7 @@ build_path = /obj/item/screwdriver category = list("initial","Tools","Tool Designs") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE + /datum/design/wirecutters name = "Wirecutters" id = "wirecutters" @@ -138,7 +139,7 @@ id = "tool_box" build_type = AUTOLATHE materials = list(MAT_CATEGORY_RIGID = 500) - build_path = /obj/item/storage/toolbox + build_path = /obj/item/storage/toolbox/greyscale category = list("initial","Tools") /datum/design/spraycan diff --git a/code/modules/research/designs/autoylathe_designs.dm b/code/modules/research/designs/autoylathe_designs.dm index 0e572fee7a..c2076db121 100644 --- a/code/modules/research/designs/autoylathe_designs.dm +++ b/code/modules/research/designs/autoylathe_designs.dm @@ -562,6 +562,7 @@ materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500) build_path = /obj/item/gun/ballistic/automatic/x9/toy category = list("initial", "Rifles") + build_type = TOYLATHE | NO_PUBLIC_LATHE /datum/design/foam_dart name = "Box of Foam Darts" @@ -586,6 +587,7 @@ materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500) build_path = /obj/item/gun/ballistic/automatic/toy/magrifle category = list("initial", "Rifles") + build_type = TOYLATHE | NO_PUBLIC_LATHE /datum/design/foam_hyperburst name = "MagTag Hyper Rifle" @@ -618,6 +620,7 @@ materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500) build_path = /obj/item/gun/ballistic/automatic/AM4C category = list("initial", "Rifles") + build_type = TOYLATHE | NO_PUBLIC_LATHE /datum/design/foam_f3 name = "Replica F3 Justicar" @@ -650,6 +653,7 @@ materials = list(/datum/material/plastic = 2000, /datum/material/iron = 250) build_path = /obj/item/gun/ballistic/automatic/toy/unrestricted category = list("initial", "Pistols") + build_type = TOYLATHE | NO_PUBLIC_LATHE /datum/design/foam_pistol name = "Foam Force Pistol" @@ -698,6 +702,7 @@ materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500) build_path = /obj/item/gun/ballistic/automatic/c20r/toy/unrestricted category = list("hacked", "Rifles") + build_type = TOYLATHE | NO_PUBLIC_LATHE /datum/design/foam_l6 name = "Donksoft LMG" @@ -706,3 +711,4 @@ materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500) build_path = /obj/item/gun/ballistic/automatic/l6_saw/toy/unrestricted category = list("hacked", "Rifles") + build_type = TOYLATHE | NO_PUBLIC_LATHE diff --git a/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm b/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm index 06cdef5ecc..d12099f7ff 100644 --- a/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm +++ b/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm @@ -107,6 +107,14 @@ departmental_flags = DEPARTMENTAL_FLAG_ALL category = list ("Medical Machinery") +/datum/design/board/paystand + name = "Machine Design (Pay Stand)" + desc = "The circuit board for a paystand." + id = "paystand" + build_path = /obj/item/circuitboard/machine/paystand + category = list ("Misc. Machinery") + departmental_flags = DEPARTMENTAL_FLAG_ALL + /datum/design/board/autoylathe name = "Machine Design (Autoylathe)" desc = "The circuit board for an autoylathe." @@ -114,3 +122,11 @@ build_path = /obj/item/circuitboard/machine/autolathe/toy departmental_flags = DEPARTMENTAL_FLAG_ALL category = list("Misc. Machinery") + +/datum/design/board/hypnochair + name = "Machine Design (Enhanced Interrogation Chamber)" + desc = "Allows for the construction of circuit boards used to build an Enhanced Interrogation Chamber." + id = "hypnochair" + departmental_flags = DEPARTMENTAL_FLAG_SECURITY + build_path = /obj/item/circuitboard/machine/hypnochair + category = list("Misc. Machinery") diff --git a/code/modules/research/designs/machine_desings/machine_designs_sci.dm b/code/modules/research/designs/machine_desings/machine_designs_sci.dm index 183977b455..59fae9d09b 100644 --- a/code/modules/research/designs/machine_desings/machine_designs_sci.dm +++ b/code/modules/research/designs/machine_desings/machine_designs_sci.dm @@ -66,6 +66,14 @@ category = list("Research Machinery") departmental_flags = DEPARTMENTAL_FLAG_SCIENCE +/datum/design/board/bepis + name = "Machine Design (B.E.P.I.S. Board)" + desc = "The circuit board for a B.E.P.I.S." + id = "bepis" + build_path = /obj/item/circuitboard/machine/bepis + category = list("Research Machinery") + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE + /datum/design/board/protolathe name = "Machine Design (Protolathe Board)" desc = "The circuit board for a protolathe." diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 5405b82848..69bf039428 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -238,7 +238,7 @@ /datum/design/bodybag name = "Body Bag" - desc = "A normal body bag used for storge of dead crew." + desc = "A normal body bag used for storage of dead crew." id = "bodybag" build_type = PROTOLATHE materials = list(/datum/material/plastic = 4000) diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index e407277ebf..e9af465c8a 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -206,6 +206,35 @@ category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING +/datum/design/bright_helmet + name = "Workplace-Ready Firefighter Helmet" + desc = "By applying state of the art lighting technology to a fire helmet with industry standard photo-chemical hardening methods, this hardhat will protect you from robust workplace hazards." + id = "bright_helmet" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 4000, /datum/material/glass = 1000, /datum/material/plastic = 3000, /datum/material/silver = 500) + build_path = /obj/item/clothing/head/hardhat/red/upgraded + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_CARGO + +/datum/design/mauna_mug + name = "Mauna Mug" + desc = "This awesome mug will ensure your coffee never stays cold!" + id = "mauna_mug" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 1000, /datum/material/glass = 100) + build_path = /obj/item/reagent_containers/glass/maunamug + category = list("Equipment") + +/datum/design/rolling_table + name = "Rolly poly" + desc = "We duct-taped some wheels to the bottom of a table. It's goddamn science alright?" + id = "rolling_table" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 4000) + build_path = /obj/structure/table/rolling + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_ALL + /datum/design/portaseeder name = "Portable Seed Extractor" desc = "For the enterprising botanist on the go. Less efficient than the stationary model, it creates one seed per plant." @@ -285,6 +314,25 @@ build_path = /obj/item/vending_refill/donksoft category = list("Equipment") +/datum/design/eng_gloves + name = "Tinkers Gloves" + desc = "Overdesigned engineering gloves that have automated construction subroutines dialed in, allowing for faster construction while worn." + id = "eng_gloves" + build_type = PROTOLATHE + materials = list(/datum/material/iron=2000, /datum/material/silver=1500, /datum/material/gold = 1000) + build_path = /obj/item/clothing/gloves/color/latex/engineering + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING + +/datum/design/lavarods + name = "Lava-Resistant Metal Rods" + id = "lava_rods" + build_type = PROTOLATHE + materials = list(/datum/material/iron=1000, /datum/material/plasma=500, /datum/material/titanium=2000) + build_path = /obj/item/stack/rods/lava + category = list("initial", "Stock Parts") + departmental_flags = DEPARTMENTAL_FLAG_CARGO | DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING + ///////////////////////////////////////// ////////////Janitor Designs////////////// ///////////////////////////////////////// diff --git a/code/modules/research/designs/tool_designs.dm b/code/modules/research/designs/tool_designs.dm index 2d938bc38c..e500166e76 100644 --- a/code/modules/research/designs/tool_designs.dm +++ b/code/modules/research/designs/tool_designs.dm @@ -72,6 +72,16 @@ category = list("Tool Designs") departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING +/datum/design/rld_mini + name = "Mini Rapid Light Device (MRLD)" + desc = "A tool that can portable and standing lighting orbs and glowsticks." + id = "rld_mini" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 20000, /datum/material/glass = 10000, /datum/material/plastic = 8000, /datum/material/gold = 2000) + build_path = /obj/item/construction/rld/mini + category = list("Tool Designs") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_CARGO + ///////////////////////////////////////// //////////////Alien Tools//////////////// ///////////////////////////////////////// diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm index 44b71a025f..8c934d39a9 100644 --- a/code/modules/research/designs/weapon_designs.dm +++ b/code/modules/research/designs/weapon_designs.dm @@ -91,7 +91,7 @@ /datum/design/mag_oldsmg name = "WT-550 Semi-Auto SMG Magazine (4.6x30mm)" - desc = "A 20 round magazine for the out of date security WT-550 Semi-Auto SMG." + desc = "A 32 round magazine for the out of date security WT-550 Semi-Auto SMG." id = "mag_oldsmg" build_type = PROTOLATHE materials = list(/datum/material/iron = 4000) @@ -101,7 +101,7 @@ /datum/design/mag_oldsmg/ap_mag name = "WT-550 Semi-Auto SMG Armour Piercing Magazine (4.6x30mm AP)" - desc = "A 20 round armour piercing magazine for the out of date security WT-550 Semi-Auto SMG." + desc = "A 32 round armour piercing magazine for the out of date security WT-550 Semi-Auto SMG." id = "mag_oldsmg_ap" materials = list(/datum/material/iron = 6000, /datum/material/silver = 600) build_path = /obj/item/ammo_box/magazine/wt550m9/wtap @@ -109,7 +109,7 @@ /datum/design/mag_oldsmg/ic_mag name = "WT-550 Semi-Auto SMG Incendiary Magazine (4.6x30mm IC)" - desc = "A 20 round armour piercing magazine for the out of date security WT-550 Semi-Auto SMG." + desc = "A 32 round armour piercing magazine for the out of date security WT-550 Semi-Auto SMG." id = "mag_oldsmg_ic" materials = list(/datum/material/iron = 6000, /datum/material/silver = 600, /datum/material/glass = 1000) build_path = /obj/item/ammo_box/magazine/wt550m9/wtic @@ -117,7 +117,7 @@ /datum/design/mag_oldsmg/tx_mag name = "WT-550 Semi-Auto SMG Uranium Magazine (4.6x30mm TX)" - desc = "A 20 round uranium tipped magazine for the out of date security WT-550 Semi-Auto SMG." + desc = "A 32 round uranium tipped magazine for the out of date security WT-550 Semi-Auto SMG." id = "mag_oldsmg_tx" materials = list(/datum/material/iron = 6000, /datum/material/silver = 600, /datum/material/uranium = 2000) build_path = /obj/item/ammo_box/magazine/wt550m9/wttx @@ -125,7 +125,7 @@ /datum/design/mag_oldsmg/rubber_mag name = "WT-550 Semi-Auto SMG rubberbullets Magazine (4.6x30mm rubber)" - desc = "A 20 round rubber shots magazine for the out of date security WT-550 Semi-Auto SMG" + desc = "A 32 round rubber shots magazine for the out of date security WT-550 Semi-Auto SMG" id = "mag_oldsmg_rubber" materials = list(/datum/material/iron = 6000) build_path = /obj/item/ammo_box/magazine/wt550m9/wtrubber @@ -135,6 +135,15 @@ //Ammo Shells/ ////////////// +/datum/design/shell_clip + name = "stripper clip (shotgun shells)" + id = "sec_shellclip" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 5000) + build_path = /obj/item/ammo_box/shotgun + category = list("Ammo") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY + /datum/design/beanbag_slug/sec id = "sec_beanbag" build_type = PROTOLATHE @@ -166,7 +175,7 @@ departmental_flags = DEPARTMENTAL_FLAG_SECURITY /datum/design/incendiary_slug/sec - id = "sec_Islug" + id = "sec_islug" build_type = PROTOLATHE category = list("Ammo") departmental_flags = DEPARTMENTAL_FLAG_SECURITY @@ -225,13 +234,13 @@ category = list("Firing Pins") departmental_flags = DEPARTMENTAL_FLAG_SECURITY -/datum/design/pin_away - name = "Station Locked Pin" - desc = "This is a security firing pin which only authorizes users who are off station." - id = "pin_away" +/datum/design/pin_explorer + name = "Outback Firing Pin" + desc = "This firing pin only shoots while ya ain't on station, fair dinkum!" + id = "pin_explorer" build_type = PROTOLATHE - materials = list(/datum/material/iron = 1500, /datum/material/glass = 2000) - build_path = /obj/item/firing_pin/away + materials = list(/datum/material/silver = 1000, /datum/material/gold = 1000, /datum/material/iron = 500) + build_path = /obj/item/firing_pin/explorer category = list("Firing Pins") departmental_flags = DEPARTMENTAL_FLAG_SECURITY @@ -491,3 +500,13 @@ materials = list(MAT_CATEGORY_RIGID = 12000) build_path = /obj/item/melee/cleric_mace category = list("Imported") + +/datum/design/stun_boomerang + name = "OZtek Boomerang" + desc = "Uses reverse flow gravitodynamics to flip its personal gravity back to the thrower mid-flight. Also functions similar to a stun baton." + id = "stun_boomerang" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 10000, /datum/material/glass = 4000, /datum/material/silver = 10000, /datum/material/gold = 2000) + build_path = /obj/item/melee/baton/boomerang + category = list("Weapons") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm index 6fca686f90..a5df3f4d12 100644 --- a/code/modules/research/machinery/_production.dm +++ b/code/modules/research/machinery/_production.dm @@ -4,7 +4,7 @@ layer = BELOW_OBJ_LAYER var/consoleless_interface = TRUE //Whether it can be used without a console. var/offstation_security_levels = TRUE - var/efficiency_coeff = 1 //Materials needed / coeff = actual. + var/print_cost_coeff = 1 //Materials needed * coeff = actual. var/list/categories = list() var/datum/component/remote_materials/materials var/allowed_department_flags = ALL @@ -76,13 +76,13 @@ for(var/obj/item/stock_parts/manipulator/M in component_parts) total_manip_rating += M.rating manips++ - efficiency_coeff = STANDARD_PART_LEVEL_LATHE_COEFFICIENT(total_manip_rating / (manips? manips : 1)) + print_cost_coeff = STANDARD_PART_LEVEL_LATHE_COEFFICIENT(total_manip_rating / (manips? manips : 1)) /obj/machinery/rnd/production/examine(mob/user) . = ..() var/datum/component/remote_materials/materials = GetComponent(/datum/component/remote_materials) if(in_range(user, src) || isobserver(user)) - . += "The status display reads: Storing up to [materials.local_size] material units locally.
Material usage efficiency at [efficiency_coeff*100]%.
" + . += "The status display reads: Storing up to [materials.local_size] material units locally.
Material usage cost at [print_cost_coeff*100]%.
" //we eject the materials upon deconstruction. /obj/machinery/rnd/production/on_deconstruction() @@ -112,7 +112,7 @@ // these types don't have their .materials set in do_print, so don't allow // them to be constructed efficiently - var/ef = efficient_with(being_built.build_path) ? efficiency_coeff : 1 + var/ef = efficient_with(being_built.build_path) ? print_cost_coeff : 1 return round(A / max(1, all_materials[mat] * ef)) /obj/machinery/rnd/production/proc/efficient_with(path) @@ -152,7 +152,7 @@ power += round(D.materials[M] * amount / 35) power = min(3000, power) use_power(power) - var/coeff = efficient_with(D.build_path) ? efficiency_coeff : 1 + var/coeff = efficient_with(D.build_path) ? print_cost_coeff : 1 var/list/efficient_mats = list() for(var/MAT in D.materials) efficient_mats[MAT] = D.materials[MAT] * coeff @@ -170,7 +170,7 @@ busy = TRUE if(production_animation) flick(production_animation, src) - var/timecoeff = D.lathe_time_factor * efficiency_coeff + var/timecoeff = D.lathe_time_factor * print_cost_coeff addtimer(CALLBACK(src, .proc/reset_busy), (20 * timecoeff * amount) ** 0.5) addtimer(CALLBACK(src, .proc/do_print, D.build_path, amount, efficient_mats, D.dangerous_construction, usr), (20 * timecoeff * amount) ** 0.5) return TRUE @@ -247,7 +247,7 @@ /obj/machinery/rnd/production/proc/ui_screen_search() var/list/l = list() - var/coeff = efficiency_coeff + var/coeff = print_cost_coeff l += "

Search Results:

" l += "
\ \ @@ -264,7 +264,7 @@ if(!istype(D)) return if(!coeff) - coeff = efficiency_coeff + coeff = print_cost_coeff if(!efficient_with(D.build_path)) coeff = 1 var/list/l = list() @@ -276,9 +276,9 @@ t = check_mat(D, M) temp_material += " | " if (t < 1) - temp_material += "[all_materials[M]/coeff] [CallMaterialName(M)]" + temp_material += "[all_materials[M] * coeff] [CallMaterialName(M)]" else - temp_material += " [all_materials[M]/coeff] [CallMaterialName(M)]" + temp_material += " [all_materials[M] * coeff] [CallMaterialName(M)]" c = min(c,t) var/clearance = !(obj_flags & EMAGGED) && (offstation_security_levels || is_station_level(z)) @@ -366,7 +366,7 @@ return ui_screen_main() var/list/l = list() l += "

Browsing [selected_category]:

" - var/coeff = efficiency_coeff + var/coeff = print_cost_coeff for(var/v in stored_research.researched_designs) var/datum/design/D = SSresearch.techweb_design_by_id(v) if(!(selected_category in D.category)|| !(D.build_type & allowed_buildtypes)) diff --git a/code/modules/research/machinery/circuit_imprinter.dm b/code/modules/research/machinery/circuit_imprinter.dm index 661ebe31c0..b80e96a1e9 100644 --- a/code/modules/research/machinery/circuit_imprinter.dm +++ b/code/modules/research/machinery/circuit_imprinter.dm @@ -25,11 +25,6 @@ /obj/machinery/rnd/production/circuit_imprinter/calculate_efficiency() . = ..() - var/total_rating = 0 - for(var/obj/item/stock_parts/manipulator/M in component_parts) - total_rating += M.rating * 2 //There is only one. - total_rating = max(1, total_rating) - efficiency_coeff = total_rating var/obj/item/circuitboard/machine/circuit_imprinter/C = circuit offstation_security_levels = C.offstation_security_levels diff --git a/code/modules/research/nanites/nanite_programs/healing.dm b/code/modules/research/nanites/nanite_programs/healing.dm index 70a1412b11..18307ce2c5 100644 --- a/code/modules/research/nanites/nanite_programs/healing.dm +++ b/code/modules/research/nanites/nanite_programs/healing.dm @@ -76,7 +76,8 @@ var/problems = FALSE if(iscarbon(host_mob)) var/mob/living/carbon/C = host_mob - if(length(C.get_traumas())) + var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN) + if(length(B?.get_traumas_type(TRAUMA_RESILIENCE_BASIC))) problems = TRUE if(host_mob.getOrganLoss(ORGAN_SLOT_BRAIN) > 0) problems = TRUE @@ -198,7 +199,8 @@ var/problems = FALSE if(iscarbon(host_mob)) var/mob/living/carbon/C = host_mob - if(length(C.get_traumas())) + var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN) + if(length(B?.get_traumas_type(TRAUMA_RESILIENCE_SURGERY))) problems = TRUE if(host_mob.getOrganLoss(ORGAN_SLOT_BRAIN) > 0) problems = TRUE @@ -208,7 +210,7 @@ host_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, -2) if(iscarbon(host_mob) && prob(10)) var/mob/living/carbon/C = host_mob - C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_LOBOTOMY) + C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_SURGERY) /datum/nanite_program/defib name = "Defibrillation" diff --git a/code/modules/research/nanites/nanite_programs/utility.dm b/code/modules/research/nanites/nanite_programs/utility.dm index 71aa5bf09a..ebe623d73d 100644 --- a/code/modules/research/nanites/nanite_programs/utility.dm +++ b/code/modules/research/nanites/nanite_programs/utility.dm @@ -144,7 +144,7 @@ return ..() /datum/nanite_program/metabolic_synthesis/active_effect() - host_mob.nutrition -= 0.5 + host_mob.adjust_nutrition(-0.5) nanites.adjust_nanites(src, 0.5) /datum/nanite_program/research diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index 9bef00d5bf..d543468c48 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -290,7 +290,7 @@ Nothing else in the console has ID requirements. continue var/temp_material var/c = 50 - var/coeff = linked_lathe.efficiency_coeff + var/coeff = linked_lathe.print_cost_coeff if(!linked_lathe.efficient_with(D.build_path)) coeff = 1 @@ -299,9 +299,9 @@ Nothing else in the console has ID requirements. var/t = linked_lathe.check_mat(D, M) temp_material += " | " if (t < 1) - temp_material += "[all_materials[M]/coeff] [CallMaterialName(M)]" + temp_material += "[all_materials[M] * coeff] [CallMaterialName(M)]" else - temp_material += " [all_materials[M]/coeff] [CallMaterialName(M)]" + temp_material += " [all_materials[M] * coeff] [CallMaterialName(M)]" c = min(c,t) var/clearance = !(linked_lathe.obj_flags & EMAGGED) && (linked_lathe.offstation_security_levels || is_station_level(linked_lathe.z)) @@ -356,16 +356,16 @@ Nothing else in the console has ID requirements. var/temp_material var/c = 50 var/all_materials = D.materials + D.reagents_list - var/coeff = linked_lathe.efficiency_coeff + var/coeff = linked_lathe.print_cost_coeff if(!linked_lathe.efficient_with(D.build_path)) coeff = 1 for(var/M in all_materials) var/t = linked_lathe.check_mat(D, M) temp_material += " | " if (t < 1) - temp_material += "[all_materials[M]/coeff] [CallMaterialName(M)]" + temp_material += "[all_materials[M] * coeff] [CallMaterialName(M)]" else - temp_material += " [all_materials[M]/coeff] [CallMaterialName(M)]" + temp_material += " [all_materials[M] * coeff] [CallMaterialName(M)]" c = min(c,t) if (c >= 1) @@ -457,7 +457,7 @@ Nothing else in the console has ID requirements. var/check_materials = TRUE var/all_materials = D.materials + D.reagents_list - var/coeff = linked_imprinter.efficiency_coeff + var/coeff = linked_imprinter.print_cost_coeff if(!linked_imprinter.efficient_with(D.build_path)) coeff = 1 @@ -465,9 +465,9 @@ Nothing else in the console has ID requirements. temp_materials += " | " if (!linked_imprinter.check_mat(D, M)) check_materials = FALSE - temp_materials += " [all_materials[M]/coeff] [CallMaterialName(M)]" + temp_materials += " [all_materials[M] * coeff] [CallMaterialName(M)]" else - temp_materials += " [all_materials[M]/coeff] [CallMaterialName(M)]" + temp_materials += " [all_materials[M] * coeff] [CallMaterialName(M)]" if (check_materials) l += "[D.name][temp_materials]" else @@ -488,16 +488,16 @@ Nothing else in the console has ID requirements. var/temp_materials var/check_materials = TRUE var/all_materials = D.materials + D.reagents_list - var/coeff = linked_imprinter.efficiency_coeff + var/coeff = linked_imprinter.print_cost_coeff if(!linked_imprinter.efficient_with(D.build_path)) coeff = 1 for(var/M in all_materials) temp_materials += " | " if (!linked_imprinter.check_mat(D, M)) check_materials = FALSE - temp_materials += " [all_materials[M]/coeff] [CallMaterialName(M)]" + temp_materials += " [all_materials[M] * coeff] [CallMaterialName(M)]" else - temp_materials += " [all_materials[M]/coeff] [CallMaterialName(M)]" + temp_materials += " [all_materials[M] * coeff] [CallMaterialName(M)]" if (check_materials) l += "[D.name][temp_materials]" else diff --git a/code/modules/research/research_disk.dm b/code/modules/research/research_disk.dm index aa781ca06b..a656093d98 100644 --- a/code/modules/research/research_disk.dm +++ b/code/modules/research/research_disk.dm @@ -21,6 +21,16 @@ . = ..() stored_research = new /datum/techweb/admin +/obj/item/disk/tech_disk/major + name = "Reformatted technology disk" + desc = "A disk containing a new, completed tech from the B.E.P.I.S. Upload the disk to an R&D Console to redeem the tech." + icon_state = "rndmajordisk" + custom_materials = list(/datum/material/iron=300, /datum/material/glass=100) + +/obj/item/disk/tech_disk/major/Initialize() + . = ..() + stored_research = new /datum/techweb/bepis + /obj/item/disk/tech_disk/illegal name = "Illegal technology disk" desc = "A technology disk containing schematics for syndicate inspired equipment." diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm index ddf6edc9f9..503bd8bae7 100644 --- a/code/modules/research/techweb/_techweb.dm +++ b/code/modules/research/techweb/_techweb.dm @@ -63,6 +63,19 @@ id = "SCIENCE" organization = "Nanotrasen" +/datum/techweb/bepis //Should contain only 1 BEPIS tech selected at random. + id = "EXPERIMENTAL" + organization = "Nanotrasen R&D" + +/datum/techweb/bepis/New() + . = ..() + var/bepis_id = pick(SSresearch.techweb_nodes_experimental) //To add a new tech to the BEPIS, add the ID to this pick list. + var/datum/techweb_node/BN = (SSresearch.techweb_node_by_id(bepis_id)) + hidden_nodes -= BN.id //Has to be removed from hidden nodes + research_node(BN, TRUE, FALSE, FALSE) + update_node_status(BN) + SSresearch.techweb_nodes_experimental -= bepis_id + /datum/techweb/Destroy() researched_nodes = null researched_designs = null @@ -126,17 +139,17 @@ modify_point_list(l) /datum/techweb/proc/copy_research_to(datum/techweb/receiver, unlock_hidden = TRUE) //Adds any missing research to theirs. + if(unlock_hidden) + for(var/i in receiver.hidden_nodes) + CHECK_TICK + if(!hidden_nodes[i]) + receiver.hidden_nodes -= i //We can see it so let them see it too. for(var/i in researched_nodes) CHECK_TICK receiver.research_node_id(i, TRUE, FALSE) for(var/i in researched_designs) CHECK_TICK receiver.add_design_by_id(i) - if(unlock_hidden) - for(var/i in receiver.hidden_nodes) - CHECK_TICK - if(!hidden_nodes[i]) - receiver.hidden_nodes -= i //We can see it so let them see it too. receiver.recalculate_nodes() /datum/techweb/proc/copy() @@ -199,6 +212,10 @@ researched_designs -= design.id return TRUE +/datum/techweb/proc/get_point_total(list/pointlist) + for(var/i in pointlist) + . += pointlist[i] + /datum/techweb/proc/can_afford(list/pointlist) for(var/i in pointlist) if(research_points[i] < pointlist[i]) @@ -227,6 +244,10 @@ for(var/id in node.design_ids) add_design_by_id(id) update_node_status(node) + if(!istype(src, /datum/techweb/admin)) + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_SCI) + if(D) + D.adjust_money(SSeconomy.techweb_bounty) return TRUE /datum/techweb/proc/unresearch_node_id(id) diff --git a/code/modules/research/techweb/_techweb_node.dm b/code/modules/research/techweb/_techweb_node.dm index fff3f42b9f..40cc322eed 100644 --- a/code/modules/research/techweb/_techweb_node.dm +++ b/code/modules/research/techweb/_techweb_node.dm @@ -7,6 +7,7 @@ var/display_name = "Errored Node" var/description = "Why are you seeing this?" var/hidden = FALSE //Whether it starts off hidden. + var/experimental = FALSE //If the tech can be randomly granted by the BEPIS as a reward. Meant to be fully given in tech disks, not researched. var/starting_node = FALSE //Whether it's available without any research. var/list/prereq_ids = list() var/list/design_ids = list() @@ -91,4 +92,17 @@ actual_costs[i] -= L[i] return actual_costs else - return research_costs \ No newline at end of file + return research_costs + +//Base Nodes, everything starts from here. + +/datum/techweb_node/base + id = "base" + starting_node = TRUE + display_name = "Basic Research Technology" + description = "NT default research technologies." + // Default research tech, prevents bricking + design_ids = list("basic_matter_bin", "basic_cell", "basic_scanning", "basic_capacitor", "basic_micro_laser", "micro_mani", "desttagger", "handlabel", "packagewrap", + "destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "bepis", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab", "paystand", + "space_heater", "beaker", "large_beaker", "bucket", "xlarge_beaker", "sec_shellclip", "sec_beanbag", "sec_rshot", "sec_bshot", "sec_slug", "sec_islug", "sec_dart", "sec_38", "sec_38lethal", + "rglass","plasteel","plastitanium","plasmaglass","plasmareinforcedglass","titaniumglass","plastitaniumglass") diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm deleted file mode 100644 index 002bb3d64b..0000000000 --- a/code/modules/research/techweb/all_nodes.dm +++ /dev/null @@ -1,1052 +0,0 @@ - -//Current rate: 132500 research points in 90 minutes - -//Base Nodes -/datum/techweb_node/base - id = "base" - starting_node = TRUE - display_name = "Basic Research Technology" - description = "NT default research technologies." - // Default research tech, prevents bricking - design_ids = list("basic_matter_bin", "basic_cell", "basic_scanning", "basic_capacitor", "basic_micro_laser", "micro_mani", "desttagger", "handlabel", "packagewrap", - "destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab", - "space_heater", "beaker", "large_beaker", "bucket", "xlarge_beaker", "sec_beanbag", "sec_rshot", "sec_bshot", "sec_slug", "sec_Islug", "sec_dart", "sec_38", "sec_38lethal", - "rglass","plasteel","plastitanium","plasmaglass","plasmareinforcedglass","titaniumglass","plastitaniumglass") - -/datum/techweb_node/mmi - id = "mmi" - starting_node = TRUE - display_name = "Man Machine Interface" - description = "A slightly Frankensteinian device that allows human brains to interface natively with software APIs." - design_ids = list("mmi") - -/datum/techweb_node/cyborg - id = "cyborg" - starting_node = TRUE - display_name = "Cyborg Construction" - description = "Sapient robots with preloaded tool modules and programmable laws." - design_ids = list("robocontrol", "sflash", "borg_suit", "borg_head", "borg_chest", "borg_r_arm", "borg_l_arm", "borg_r_leg", "borg_l_leg", "borgupload", - "cyborgrecharger", "borg_upgrade_restart", "borg_upgrade_rename") - -/datum/techweb_node/mech - id = "mecha" - starting_node = TRUE - display_name = "Mechanical Exosuits" - description = "Mechanized exosuits that are several magnitudes stronger and more powerful than the average human." - design_ids = list("mecha_tracking", "mechacontrol", "mechapower", "mech_recharger", "ripley_chassis", "firefighter_chassis", "ripley_torso", "ripley_left_arm", "ripley_right_arm", "ripley_left_leg", "ripley_right_leg", - "ripley_main", "ripley_peri", "mech_hydraulic_clamp") - -/datum/techweb_node/mech_tools - id = "mech_tools" - starting_node = TRUE - display_name = "Basic Exosuit Equipment" - description = "Various tools fit for basic mech units" - design_ids = list("mech_drill", "mech_mscanner", "mech_extinguisher", "mech_cable_layer") - -/datum/techweb_node/surplus_lims - id = "surplus_lims" - display_name = "Basic Prosthetics" - description = "Basic fragile lims for the impaired." - starting_node = TRUE - prereq_ids = list("biotech") - design_ids = list("basic_l_arm", "basic_r_arm", "basic_r_leg", "basic_l_leg") - -/datum/techweb_node/blueprinted_bottles - id = "blueprinted_bottles" - display_name = "License Bottling" - description = "Some Branded bottles to print and export." - starting_node = TRUE - design_ids = list("gin", "wine", "whiskey", "vodka", "tequila", "patron", "rum", "kahlua", "vermouth", "goldschlager", "hcider", "cognac", "absinthe", "grappa", "sake", "fernet", "applejack", "champagne", "blazaam", "trappist", "grenadine", "autobottler") - -/datum/techweb_node/blueprinted_exports - id = "blueprinted_exports" - display_name = "License Exports" - description = "Some Branded bottles to print and export." - starting_node = TRUE - design_ids = list("gin_export", "wine_export", "whiskey_export", "vodka_export", "tequila_export", "patron_export", "rum_export", "kahlua_export", "vermouth_export", "goldschlager_export", "hcider_export", "cognac_export", "absinthe_export", "grappa_export", "sake_export", "fernet_export", "applejack_export", "champagne_export", "blazaam_export", "trappist_export", "grenadine_export") - -/////////////////////////Biotech///////////////////////// -/datum/techweb_node/biotech - id = "biotech" - display_name = "Biological Technology" - description = "What makes us tick." //the MC, silly! - prereq_ids = list("base") - design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibrillator", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen", "telescopiciv", "medspray","genescanner") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/adv_biotech - id = "adv_biotech" - display_name = "Advanced Biotechnology" - description = "Advanced Biotechnology" - prereq_ids = list("biotech") - design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "meta_beaker", "healthanalyzer_advanced", "harvester", "holobarrier_med", "defibrillator_compact", "smartdartgun", "medicinalsmartdart", "pHmeter", "containmentbodybag") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/bio_process - id = "bio_process" - display_name = "Biological Processing" - description = "From slimes to kitchens." - prereq_ids = list("biotech") - design_ids = list("smartfridge", "gibber", "deepfryer", "monkey_recycler", "processor", "gibber", "microwave", "reagentgrinder", "dish_drive") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/bottle_exports - id = "bottle_exports" - display_name = "Legal Bottling" - prereq_ids = list("blueprinted_bottles") - description = "New bottles for printing and selling." - design_ids = list("minikeg", "blooddrop", "slim_gold", "white_bloodmoon", "greenroad") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 250) - -/datum/techweb_node/advance_lims - id = "advance_lims" - display_name = "Upgraded Prosthetics" - description = "Reinforced prosthetics for the impaired." - prereq_ids = list("adv_biotech", "surplus_lims") - design_ids = list("adv_l_arm", "adv_r_arm", "adv_r_leg", "adv_l_leg") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) - -/datum/techweb_node/advance_surgerytools - id = "advance_surgerytools" - display_name = "Advanced Surgery Tools" - description = "Refined and improved redesigns for the run-of-the-mill medical utensils." - prereq_ids = list("adv_biotech", "adv_surgery") - design_ids = list("drapes", "retractor_adv", "surgicaldrill_adv", "scalpel_adv") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/adv_defibrillator_tec - id = "adv_defibrillator_tec" - display_name = "Defibrillator Upgrades" - description = "More ways to bring back the newly dead." - prereq_ids = list("adv_biotech", "exp_surgery", "adv_engi", "adv_power") - design_ids = list("defib_decay", "defib_shock", "defib_heal", "defib_speed") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/////////////////////////Advanced Surgery///////////////////////// -/datum/techweb_node/imp_wt_surgery - id = "imp_wt_surgery" - display_name = "Improved Wound-Tending Surgery" - description = "Who would have known being more gentle with a hemostat decreases patient pain?" - prereq_ids = list("biotech") - design_ids = list("surgery_heal_brute_upgrade","surgery_heal_burn_upgrade") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) - -/datum/techweb_node/adv_surgery - id = "adv_surgery" - display_name = "Advanced Surgery" - description = "When simple medicine doesn't cut it." - prereq_ids = list("imp_wt_surgery") - design_ids = list("surgery_revival", "surgery_lobotomy", "surgery_heal_brute_upgrade_femto","surgery_heal_burn_upgrade_femto", "surgery_heal_combo", "surgery_toxinhealing", "organbox", "surgery_adv_dissection") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/exp_surgery - id = "exp_surgery" - display_name = "Experimental Surgery" - description = "When evolution isn't fast enough." - prereq_ids = list("adv_surgery") - design_ids = list("surgery_pacify","surgery_vein_thread","surgery_muscled_veins","surgery_nerve_splice","surgery_nerve_ground","surgery_ligament_hook","surgery_ligament_reinforcement","surgery_viral_bond", "surgery_exp_dissection", "surgery_heal_combo_upgrade") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - -/datum/techweb_node/alien_surgery - id = "alien_surgery" - display_name = "Alien Surgery" - description = "Abductors did nothing wrong." - prereq_ids = list("exp_surgery", "alientech") - design_ids = list("surgery_brainwashing","surgery_zombie", "surgery_ext_dissection", "surgery_heal_combo_upgrade_femto") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - -/////////////////////////data theory tech///////////////////////// -/datum/techweb_node/datatheory //Computer science - id = "datatheory" - display_name = "Data Theory" - description = "Big Data, in space!" - prereq_ids = list("base") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/adv_datatheory - id = "adv_datatheory" - display_name = "Advanced Data Theory" - description = "Better insight into programming and data." - prereq_ids = list("datatheory") - design_ids = list("icprinter", "icupgadv", "icupgclo") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - -/////////////////////////engineering tech///////////////////////// -/datum/techweb_node/engineering - id = "engineering" - display_name = "Industrial Engineering" - description = "A refresher course on modern engineering technology." - prereq_ids = list("base") - design_ids = list("solarcontrol", "recharger", "powermonitor", "rped", "pacman", "adv_capacitor", "adv_scanning", "emitter", "high_cell", "adv_matter_bin", - "atmosalerts", "atmos_control", "recycler", "autolathe", "autolathe_secure", "high_micro_laser", "nano_mani", "mesons", "thermomachine", "rad_collector", "tesla_coil", "grounding_rod", - "apc_control", "power control", "airlock_board", "firelock_board", "airalarm_electronics", "firealarm_electronics", "cell_charger", "stack_console", "stack_machine", "rcd_ammo") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 6000) - -/datum/techweb_node/adv_engi - id = "adv_engi" - display_name = "Advanced Engineering" - description = "Pushing the boundaries of physics, one chainsaw-fist at a time." - prereq_ids = list("engineering", "emp_basic") - design_ids = list("engine_goggles", "magboots", "forcefield_projector", "weldingmask" , "rcd_loaded", "rpd", "tray_goggles_prescription", "engine_goggles_prescription", "mesons_prescription", "rcd_upgrade_frames", "rcd_upgrade_simple_circuits", "rcd_ammo_large") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) - -/datum/techweb_node/anomaly - id = "anomaly_research" - display_name = "Anomaly Research" - description = "Unlock the potential of the mysterious anomalies that appear on station." - prereq_ids = list("adv_engi", "practical_bluespace") - design_ids = list("reactive_armour", "anomaly_neutralizer") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) - -/datum/techweb_node/high_efficiency - id = "high_efficiency" - display_name = "High Efficiency Parts" - description = "Finely-tooled manufacturing techniques allowing for picometer-perfect precision levels." - prereq_ids = list("engineering", "datatheory") - design_ids = list("pico_mani", "super_matter_bin") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - -/datum/techweb_node/adv_power - id = "adv_power" - display_name = "Advanced Power Manipulation" - description = "How to get more zap." - prereq_ids = list("engineering") - design_ids = list("smes", "super_cell", "hyper_cell", "super_capacitor", "superpacman", "mrspacman", "power_turbine", "power_turbine_console", "power_compressor", "circulator", "teg") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - -/* -/datum/techweb_node/basic_meteor_defense - id = "basic_meteor_defense" - display_name = "Meteor Defense Research" - description = "Unlock the potential of the mysterious of why CC decided to not build these around the station themselves." - prereq_ids = list("adv_engi", "high_efficiency") - design_ids = list("meteor_defence", "meteor_console") - -/datum/techweb_node/adv_meteor_defense - id = "adv_meteor_defense" - display_name = "Meteor Defense Research" - description = "New and improved coding and lock on tech for meteor defence!" - prereq_ids = list("basic_meteor_defense", "adv_datatheory", "emp_adv") - design_ids = list("meteor_disk") -*/ - -/datum/techweb_node/computer_board_gaming - id = "computer_board_gaming" - display_name = "Games and Toys" - description = "For the slackers on the station." - prereq_ids = list("comptech") - design_ids = list("arcade_battle", "arcade_orion", "arcade_minesweeper", "slotmachine", "autoylathe") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) - -/////////////////////////Bluespace tech///////////////////////// -/datum/techweb_node/bluespace_basic //Bluespace-memery - id = "bluespace_basic" - display_name = "Basic Bluespace Theory" - description = "Basic studies into the mysterious alternate dimension known as bluespace." - prereq_ids = list("base", "datatheory") - design_ids = list("beacon", "xenobioconsole", "telesci_gps", "xenobio_monkeys") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/practical_bluespace - id = "practical_bluespace" - display_name = "Applied Bluespace Research" - description = "Using bluespace to make things faster and better." - prereq_ids = list("bluespace_basic", "engineering") - design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - -/datum/techweb_node/adv_bluespace - id = "adv_bluespace" - display_name = "Advanced Bluespace Research" - description = "Deeper understanding of how the Bluespace dimension works" - prereq_ids = list("practical_bluespace", "high_efficiency") - design_ids = list("bluespace_matter_bin", "femto_mani", "triphasic_scanning", "bluespace_crystal", "xenobio_slimeadv") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - -/datum/techweb_node/bluespace_power - id = "bluespace_power" - display_name = "Bluespace Power Technology" - description = "Even more powerful.. power!" - prereq_ids = list("adv_power", "adv_bluespace") - design_ids = list("bluespace_cell", "quadratic_capacitor") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/bluespace_holding - id = "bluespace_holding" - display_name = "Bluespace Pockets" - description = "Studies into the mysterious alternate dimension known as bluespace and how to place items in the threads of reality." - prereq_ids = list("adv_power", "adv_bluespace", "adv_biotech", "adv_plasma") - design_ids = list( "bluespacebodybag","bag_holding", "bluespace_pod", "borg_upgrade_trashofholding", "blutrash", "satchel_holding", "bsblood_bag", "duffelbag_holding") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5500) - -/datum/techweb_node/bluespace_portal - id = "bluespace_portal" - display_name = "Bluespace Portals" - description = "Allows for Bluespace Tech to be used tandem with Wormhole tech." - prereq_ids = list("adv_weaponry", "adv_bluespace") - design_ids = list("wormholeprojector") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/bluespace_warping - id = "bluespace_warping" - display_name = "Bluespace Travel" - description = "Application of Bluespace for static teleportation technology." - prereq_ids = list("adv_power", "adv_bluespace") - design_ids = list("tele_station", "tele_hub", "quantumpad", "quantum_keycard", "launchpad", "launchpad_console", "teleconsole", "roastingstick") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/unregulated_bluespace - id = "unregulated_bluespace" - display_name = "Unregulated Bluespace Research" - description = "Bluespace technology using unstable or unbalanced procedures, prone to damaging the fabric of bluespace. Outlawed by galactic conventions." - prereq_ids = list("bluespace_warping", "syndicate_basic") - design_ids = list("desynchronizer") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/////////////////////////plasma tech///////////////////////// -/datum/techweb_node/basic_plasma - id = "basic_plasma" - display_name = "Basic Plasma Research" - description = "Research into the mysterious and dangerous substance, plasma." - prereq_ids = list("engineering") - design_ids = list("mech_generator") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/adv_plasma - id = "adv_plasma" - display_name = "Advanced Plasma Research" - description = "Research on how to fully exploit the power of plasma." - prereq_ids = list("basic_plasma") - design_ids = list("mech_plasma_cutter") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - -/////////////////////////robotics tech///////////////////////// -/datum/techweb_node/robotics - id = "robotics" - display_name = "Basic Robotics Research" - description = "Programmable machines that make our lives lazier." - prereq_ids = list("base") - design_ids = list("paicard", "drone_shell") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/adv_robotics - id = "adv_robotics" - display_name = "Advanced Robotics Research" - description = "It can even do the dishes!" - prereq_ids = list("robotics") - design_ids = list("borg_upgrade_diamonddrill", "borg_upgrade_advancedmop", "borg_upgrade_advcutter") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - -/datum/techweb_node/neural_programming - id = "neural_programming" - display_name = "Neural Programming" - description = "Study into networks of processing units that mimic our brains." - prereq_ids = list("biotech", "datatheory") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/posibrain - id = "posibrain" - display_name = "Positronic Brain" - description = "Applied usage of neural technology allowing for autonomous AI units based on special metallic cubes with conductive and processing circuits." - prereq_ids = list("neural_programming") - design_ids = list("mmi_posi") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/cyborg_upg_util - id = "cyborg_upg_util" - display_name = "Cyborg Upgrades: Utility" - description = "Utility upgrades for cyborgs." - prereq_ids = list("engineering", "robotics") - design_ids = list("borg_upgrade_lavaproof", "borg_upgrade_thrusters", "borg_upgrade_selfrepair", "borg_upgrade_expand", "borg_upgrade_rped") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/cyborg_upg_med - id = "cyborg_upg_med" - display_name = "Cyborg Upgrades: Medical" - description = "Medical upgrades for cyborgs." - prereq_ids = list("adv_biotech", "robotics") - design_ids = list("borg_upgrade_advhealth", "borg_upgrade_piercinghypospray", "borg_upgrade_highstrengthsynthesiser", "borg_upgrade_expandedsynthesiser", "borg_upgrade_pinpointer", "borg_upgrade_surgicalprocessor") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/cyborg_upg_combat - id = "cyborg_upg_combat" - display_name = "Cyborg Upgrades: Combat" - description = "Military grade upgrades for cyborgs." - prereq_ids = list("adv_robotics", "adv_engi" , "weaponry") - design_ids = list("borg_upgrade_vtec", "borg_upgrade_disablercooler") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - -/datum/techweb_node/ai - id = "ai" - display_name = "Artificial Intelligence" - description = "AI unit research." - prereq_ids = list("robotics", "posibrain") - design_ids = list("aifixer", "aicore", "safeguard_module", "onehuman_module", "protectstation_module", "quarantine_module", "oxygen_module", "freeform_module", - "reset_module", "purge_module", "remove_module", "freeformcore_module", "asimov_module", "paladin_module", "tyrant_module", "corporate_module", - "default_module", "borg_ai_control", "mecha_tracking_ai_control", "aiupload", "intellicard") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/////////////////////////EMP tech///////////////////////// -/datum/techweb_node/emp_basic //EMP tech for some reason - id = "emp_basic" - display_name = "Electromagnetic Theory" - description = "Study into usage of frequencies in the electromagnetic spectrum." - prereq_ids = list("base") - design_ids = list("holosign", "holosignsec", "holosignengi", "holosignatmos", "holosignfirelock", "inducer", "tray_goggles", "holopad") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/emp_adv - id = "emp_adv" - display_name = "Advanced Electromagnetic Theory" - description = "Determining whether reversing the polarity will actually help in a given situation." - prereq_ids = list("emp_basic") - design_ids = list("ultra_micro_laser") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - -/datum/techweb_node/emp_super - id = "emp_super" - display_name = "Quantum Electromagnetic Technology" //bs - description = "Even better electromagnetic technology." - prereq_ids = list("emp_adv") - design_ids = list("quadultra_micro_laser") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - -/////////////////////////Clown tech///////////////////////// -/datum/techweb_node/clown - id = "clown" - display_name = "Clown Technology" - description = "Honk?!" - prereq_ids = list("base") - design_ids = list("air_horn", "honker_main", "honker_peri", "honker_targ", "honk_chassis", "honk_head", "honk_torso", "honk_left_arm", "honk_right_arm", - "honk_left_leg", "honk_right_leg", "mech_banana_mortar", "mech_mousetrap_mortar", "mech_honker", "mech_punching_face", "implant_trombone", "borg_transform_clown") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -////////////////////////Computer tech//////////////////////// -/datum/techweb_node/comptech - id = "comptech" - display_name = "Computer Consoles" - description = "Computers and how they work." - prereq_ids = list("datatheory") - design_ids = list("cargo", "cargorequest", "libraryconsole", "mining", "miningshuttle", "crewconsole", "rdcamera", "comconsole", "idcardconsole", "seccamera") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/computer_hardware_basic //Modular computers are shitty and nearly useless so until someone makes them actually useful this can be easy to get. - id = "computer_hardware_basic" - display_name = "Computer Hardware" - description = "How computer hardware are made." - prereq_ids = list("comptech") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) //they are really kinda shitty - design_ids = list("hdd_basic", "hdd_advanced", "hdd_super", "hdd_cluster", "ssd_small", "ssd_micro", "netcard_basic", "netcard_advanced", "netcard_wired", - "portadrive_basic", "portadrive_advanced", "portadrive_super", "cardslot", "aislot", "miniprinter", "APClink", "bat_control", "bat_normal", "bat_advanced", - "bat_super", "bat_micro", "bat_nano", "cpu_normal", "pcpu_normal", "cpu_small", "pcpu_small") - -/datum/techweb_node/comp_recordkeeping - id = "comp_recordkeeping" - display_name = "Computerized Recordkeeping" - description = "Organized record databases and how they're used." - prereq_ids = list("comptech") - design_ids = list("secdata", "med_data", "prisonmanage", "vendor", "automated_announcement") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) - -/datum/techweb_node/telecomms - id = "telecomms" - display_name = "Telecommunications Technology" - description = "Subspace transmission technology for near-instant communications devices." - prereq_ids = list("comptech", "bluespace_basic") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) - design_ids = list("s-receiver", "s-bus", "s-broadcaster", "s-processor", "s-hub", "s-server", "s-relay", "comm_monitor", "comm_server", - "s-ansible", "s-filter", "s-amplifier", "ntnet_relay", "s-treatment", "s-analyzer", "s-crystal", "s-transmitter", "message_monitor") - -/datum/techweb_node/integrated_HUDs - id = "integrated_HUDs" - display_name = "Integrated HUDs" - description = "The usefulness of computerized records, projected straight onto your eyepiece!" - prereq_ids = list("comp_recordkeeping", "emp_basic") - design_ids = list("health_hud", "security_hud", "diagnostic_hud", "scigoggles", "health_hud_prescription", "security_hud_prescription", "diagnostic_hud_prescription") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) - -/datum/techweb_node/NVGtech - id = "NVGtech" - display_name = "Night Vision Technology" - description = "Allows seeing in the dark without actual light!" - prereq_ids = list("integrated_HUDs", "adv_engi", "emp_adv") - design_ids = list("health_hud_night", "security_hud_night", "diagnostic_hud_night", "night_visision_goggles", "nvgmesons", "night_visision_goggles_glasses") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - -////////////////////////Medical//////////////////////// -/datum/techweb_node/cloning - id = "cloning" - display_name = "Genetic Engineering" - description = "We have the technology to make him." - prereq_ids = list("biotech") - design_ids = list("clonecontrol", "clonepod", "clonescanner", "scan_console", "cloning_disk") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/cryotech - id = "cryotech" - display_name = "Cryostasis Technology" - description = "Smart freezing of objects to preserve them!" - prereq_ids = list("adv_engi", "biotech") - design_ids = list("splitbeaker", "noreactsyringe", "cryotube", "cryo_Grenade") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/subdermal_implants - id = "subdermal_implants" - display_name = "Subdermal Implants" - description = "Electronic implants buried beneath the skin." - prereq_ids = list("biotech", "datatheory") - design_ids = list("implanter", "implantcase", "implant_chem", "implant_tracking", "locator", "c38_trac") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/cyber_organs - id = "cyber_organs" - display_name = "Cybernetic Organs" - description = "We have the technology to rebuild him." - prereq_ids = list("adv_biotech") - design_ids = list("cybernetic_ears", "cybernetic_heart", "cybernetic_liver", "cybernetic_lungs", "cybernetic_tongue") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) - -/datum/techweb_node/cyber_organs_upgraded - id = "cyber_organs_upgraded" - display_name = "Upgraded Cybernetic Organs" - description = "We have the technology to upgrade him." - prereq_ids = list("cyber_organs") - design_ids = list("cybernetic_ears_u", "cybernetic_heart_u", "cybernetic_liver_u", "cybernetic_lungs_u") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) - -/datum/techweb_node/cyber_implants - id = "cyber_implants" - display_name = "Cybernetic Implants" - description = "Electronic implants that improve humans." - prereq_ids = list("adv_biotech", "adv_datatheory") - design_ids = list("ci-nutriment", "ci-breather", "ci-gloweyes", "ci-welding", "ci-medhud", "ci-sechud", "ci-service") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/adv_cyber_implants - id = "adv_cyber_implants" - display_name = "Advanced Cybernetic Implants" - description = "Upgraded and more powerful cybernetic implants." - prereq_ids = list("neural_programming", "cyber_implants","integrated_HUDs") - design_ids = list("ci-toolset", "ci-surgery", "ci-reviver", "ci-nutrimentplus") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/combat_cyber_implants - id = "combat_cyber_implants" - display_name = "Combat Cybernetic Implants" - description = "Military grade combat implants to improve performance." - prereq_ids = list("adv_cyber_implants","weaponry","NVGtech","high_efficiency") - design_ids = list("ci-xray", "ci-thermals", "ci-antidrop", "ci-antistun", "ci-thrusters", "ci-shield") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -////////////////////////Tools//////////////////////// -/datum/techweb_node/basic_tools - id = "basic_tools" - display_name = "Basic Tools" - description = "Basic mechanical, electronic, surgical and botanical tools." - prereq_ids = list("base") - design_ids = list("screwdriver", "wrench", "wirecutters", "crowbar", "multitool", "welding_tool", "tscanner", "analyzer", "cable_coil", "pipe_painter", "airlock_painter", "scalpel", "circular_saw", "surgicaldrill", "retractor", "cautery", "hemostat", "cultivator", "plant_analyzer", "shovel", "spade", "hatchet", "mop", "broom", "normtrash") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 500) - -/datum/techweb_node/basic_mining - id = "basic_mining" - display_name = "Mining Technology" - description = "Better than Efficiency V." - prereq_ids = list("engineering", "basic_plasma") - design_ids = list("drill", "superresonator", "triggermod", "damagemod", "cooldownmod", "rangemod", "ore_redemption", "mining_equipment_vendor", "cargoexpress", "plasmacutter")//e a r l y g a m e) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/adv_mining - id = "adv_mining" - display_name = "Advanced Mining Technology" - description = "Efficiency Level 127" //dumb mc references - prereq_ids = list("basic_mining", "adv_engi", "adv_power", "adv_plasma") - design_ids = list("drill_diamond", "jackhammer", "hypermod", "plasmacutter_adv", "ore_silo", "plasteel_pick", "titanium_pick") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/janitor - id = "janitor" - display_name = "Advanced Sanitation Technology" - description = "Clean things better, faster, stronger, and harder!" - prereq_ids = list("adv_engi") - design_ids = list("advmop", "buffer", "light_replacer", "spraybottle", "beartrap", "ci-janitor", "paint_remover") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1750) // No longer has its bag - -/datum/techweb_node/botany - id = "botany" - display_name = "Botanical Engineering" - description = "Botanical tools." - prereq_ids = list("adv_engi", "biotech") - design_ids = list("diskplantgene", "portaseeder", "plantgenes", "flora_gun", "hydro_tray", "biogenerator", "seed_extractor") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) - -/datum/techweb_node/exp_tools - id = "exp_tools" - display_name = "Experimental Tools" - description = "Highly advanced construction tools." - design_ids = list("exwelder", "jawsoflife", "handdrill", "holosigncombifan") - prereq_ids = list("adv_engi") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) - -/datum/techweb_node/sec_basic - id = "sec_basic" - display_name = "Basic Security Equipment" - description = "Standard equipment used by security." - design_ids = list("seclite", "pepperspray", "bola_energy", "zipties", "evidencebag") - prereq_ids = list("base") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 750) - -/////////////////////////weaponry tech///////////////////////// -/datum/techweb_node/weaponry - id = "weaponry" - display_name = "Weapon Development Technology" - description = "Our researchers have found new to weaponize just about everything now." - prereq_ids = list("engineering") - design_ids = list("pin_testing", "tele_shield", "lasercarbine", "pin_away") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) - -/datum/techweb_node/adv_weaponry - id = "adv_weaponry" - display_name = "Advanced Weapon Development Technology" - description = "Our weapons are breaking the rules of reality by now." - prereq_ids = list("adv_engi", "weaponry") - design_ids = list("pin_loyalty", "laser_shield", "bullet_shield") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) - -/datum/techweb_node/electric_weapons - id = "electronic_weapons" - display_name = "Electric Weapons" - description = "Weapons using electric technology" - prereq_ids = list("weaponry", "adv_power" , "emp_basic") - design_ids = list("stunrevolver", "stunshell", "ioncarbine") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) - -/datum/techweb_node/radioactive_weapons - id = "radioactive_weapons" - display_name = "Radioactive Weaponry" - description = "Weapons using radioactive technology." - prereq_ids = list("adv_engi", "adv_weaponry") - design_ids = list("nuclear_gun") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/magnetic_weapons - id = "magnetic_weapons" - display_name = "Magnetic Weapons" - description = "Weapons using magnetic technology" - prereq_ids = list("weaponry", "adv_weaponry", "emp_adv") - design_ids = list("magrifle", "magpistol", "mag_magrifle", "mag_magrifle_nl", "mag_magpistol", "mag_magpistol_nl") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/medical_weapons - id = "medical_weapons" - display_name = "Medical Weaponry" - description = "Weapons using medical technology." - prereq_ids = list("adv_biotech", "adv_weaponry") - design_ids = list("rapidsyringe", "shotgundartcryostatis") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/beam_weapons - id = "beam_weapons" - display_name = "Beam Weaponry" - description = "Various basic beam weapons" - prereq_ids = list("adv_weaponry") - design_ids = list("temp_gun", "xray_laser") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/adv_beam_weapons - id = "adv_beam_weapons" - display_name = "Advanced Beam Weaponry" - description = "Various advanced beam weapons" - prereq_ids = list("beam_weapons") - design_ids = list("beamrifle") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3250) // Sniper - -/datum/techweb_node/explosive_weapons - id = "explosive_weapons" - display_name = "Explosive & Pyrotechnical Weaponry" - description = "If the light stuff just won't do it." - prereq_ids = list("adv_weaponry") - design_ids = list("large_Grenade", "pyro_Grenade", "adv_Grenade") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) - -/datum/techweb_node/ballistic_weapons - id = "ballistic_weapons" - display_name = "Ballistic Weaponry" - description = "This isn't research.. This is reverse-engineering!" - prereq_ids = list("weaponry") - design_ids = list("mag_oldsmg", "mag_oldsmg_ap", "mag_oldsmg_ic", "mag_oldsmg_rubber", "mag_oldsmg_tx") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) - -/datum/techweb_node/exotic_ammo - id = "exotic_ammo" - display_name = "Exotic Ammunition" - description = "They won't know what hit em." - prereq_ids = list("weaponry", "ballistic_weapons") - design_ids = list("techshotshell", "c38_hotshot", "c38_iceblox") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) - -/datum/techweb_node/gravity_gun - id = "gravity_gun" - display_name = "One-point Bluespace-gravitational Manipulator" - description = "Fancy wording for gravity gun." - prereq_ids = list("adv_weaponry", "adv_bluespace") - design_ids = list("gravitygun", "mech_gravcatapult") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -////////////////////////mech technology//////////////////////// -/datum/techweb_node/adv_mecha - id = "adv_mecha" - display_name = "Advanced Exosuits" - description = "For when you just aren't Gundam enough." - prereq_ids = list("adv_robotics") - design_ids = list("mech_repair_droid") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/odysseus - id = "mecha_odysseus" - display_name = "EXOSUIT: Odysseus" - description = "Odysseus exosuit designs" - prereq_ids = list("base") - design_ids = list("odysseus_chassis", "odysseus_torso", "odysseus_head", "odysseus_left_arm", "odysseus_right_arm" ,"odysseus_left_leg", "odysseus_right_leg", - "odysseus_main", "odysseus_peri") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/gygax - id = "mech_gygax" - display_name = "EXOSUIT: Gygax" - description = "Gygax exosuit designs" - prereq_ids = list("adv_mecha", "weaponry") - design_ids = list("gygax_chassis", "gygax_torso", "gygax_head", "gygax_left_arm", "gygax_right_arm", "gygax_left_leg", "gygax_right_leg", "gygax_main", - "gygax_peri", "gygax_targ", "gygax_armor") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/durand - id = "mech_durand" - display_name = "EXOSUIT: Durand" - description = "Durand exosuit designs" - prereq_ids = list("adv_mecha", "adv_weaponry") - design_ids = list("durand_chassis", "durand_torso", "durand_head", "durand_left_arm", "durand_right_arm", "durand_left_leg", "durand_right_leg", "durand_main", - "durand_peri", "durand_targ", "durand_armor") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) - -/datum/techweb_node/phazon - id = "mecha_phazon" - display_name = "EXOSUIT: Phazon" - description = "Phazon exosuit designs" - prereq_ids = list("adv_mecha", "weaponry" , "adv_bluespace") - design_ids = list("phazon_chassis", "phazon_torso", "phazon_head", "phazon_left_arm", "phazon_right_arm", "phazon_left_leg", "phazon_right_leg", "phazon_main", - "phazon_peri", "phazon_targ", "phazon_armor") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - -/datum/techweb_node/adv_mecha_tools - id = "adv_mecha_tools" - display_name = "Advanced Exosuit Equipment" - description = "Tools for high level mech suits" - prereq_ids = list("adv_mecha") - design_ids = list("mech_rcd") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/med_mech_tools - id = "med_mech_tools" - display_name = "Medical Exosuit Equipment" - description = "Tools for high level mech suits" - prereq_ids = list("adv_biotech") - design_ids = list("mech_sleeper", "mech_syringe_gun", "mech_medi_beam") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/mech_modules - id = "adv_mecha_modules" - display_name = "Simple Exosuit Modules" - description = "An advanced piece of mech weaponry" - prereq_ids = list("adv_mecha", "bluespace_power") - design_ids = list("mech_energy_relay", "mech_ccw_armor", "mech_proj_armor", "mech_generator_nuclear") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_scattershot - id = "mecha_tools" - display_name = "Exosuit Weapon (LBX AC 10 \"Scattershot\")" - description = "An advanced piece of mech weaponry" - prereq_ids = list("ballistic_weapons") - design_ids = list("mech_scattershot", "mech_scattershot_ammo") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_seedscatter - id = "mech_seedscatter" - display_name = "Exosuit Weapon (Melon Seed \"Scattershot\")" - description = "An advanced piece of mech weaponry" - prereq_ids = list("ballistic_weapons") - design_ids = list("mech_seedscatter") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_carbine - id = "mech_carbine" - display_name = "Exosuit Weapon (FNX-99 \"Hades\" Carbine)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("ballistic_weapons") - design_ids = list("mech_carbine", "mech_carbine_ammo") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_ion - id = "mmech_ion" - display_name = "Exosuit Weapon (MKIV Ion Heavy Cannon)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("electronic_weapons", "emp_adv") - design_ids = list("mech_ion") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_tesla - id = "mech_tesla" - display_name = "Exosuit Weapon (MKI Tesla Cannon)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("electronic_weapons", "adv_power") - design_ids = list("mech_tesla") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_laser - id = "mech_laser" - display_name = "Exosuit Weapon (CH-PS \"Immolator\" Laser)" - description = "A basic piece of mech weaponry" - prereq_ids = list("beam_weapons") - design_ids = list("mech_laser") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_laser_heavy - id = "mech_laser_heavy" - display_name = "Exosuit Weapon (CH-LC \"Solaris\" Laser Cannon)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("adv_beam_weapons") - design_ids = list("mech_laser_heavy") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_grenade_launcher - id = "mech_grenade_launcher" - display_name = "Exosuit Weapon (SGL-6 Grenade Launcher)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("explosive_weapons") - design_ids = list("mech_grenade_launcher", "mech_grenade_launcher_ammo") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_missile_rack - id = "mech_missile_rack" - display_name = "Exosuit Weapon (BRM-6 Missile Rack)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("explosive_weapons") - design_ids = list("mech_missile_rack", "mech_missile_rack_ammo") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/clusterbang_launcher - id = "clusterbang_launcher" - display_name = "Exosuit Module (SOB-3 Clusterbang Launcher)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("explosive_weapons") - design_ids = list("clusterbang_launcher", "clusterbang_launcher_ammo") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_teleporter - id = "mech_teleporter" - display_name = "Exosuit Module (Teleporter Module)" - description = "An advanced piece of mech Equipment" - prereq_ids = list("adv_bluespace") - design_ids = list("mech_teleporter") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_wormhole_gen - id = "mech_wormhole_gen" - display_name = "Exosuit Module (Localized Wormhole Generator)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("adv_bluespace") - design_ids = list("mech_wormhole_gen") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_taser - id = "mech_taser" - display_name = "Exosuit Weapon (PBT \"Pacifier\" Mounted Taser)" - description = "A basic piece of mech weaponry" - prereq_ids = list("electronic_weapons") - design_ids = list("mech_taser") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_lmg - id = "mech_lmg" - display_name = "Exosuit Weapon (\"Ultra AC 2\" LMG)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("ballistic_weapons") - design_ids = list("mech_lmg", "mech_lmg_ammo") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_diamond_drill - id = "mech_diamond_drill" - display_name = "Exosuit Diamond Drill" - description = "A diamond drill fit for a large exosuit" - prereq_ids = list("adv_mining") - design_ids = list("mech_diamond_drill") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/////////////////////////Nanites///////////////////////// -/datum/techweb_node/nanite_base - id = "nanite_base" - display_name = "Basic Nanite Programming" - description = "The basics of nanite construction and programming." - prereq_ids = list("datatheory","robotics") - design_ids = list("nanite_disk","nanite_remote","nanite_comm_remote","nanite_scanner",\ - "nanite_chamber","public_nanite_chamber","nanite_chamber_control","nanite_programmer","nanite_program_hub","nanite_cloud_control",\ - "relay_nanites", "monitoring_nanites", "access_nanites", "repairing_nanites","sensor_nanite_volume", "repeater_nanites", "relay_repeater_nanites","red_diag_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/nanite_smart - id = "nanite_smart" - display_name = "Smart Nanite Programming" - description = "Nanite programs that require nanites to perform complex actions, act independently, roam or seek targets." - prereq_ids = list("nanite_base","adv_robotics") - design_ids = list("purging_nanites", "research_nanites", "metabolic_nanites", "stealth_nanites", "memleak_nanites","sensor_voice_nanites", "voice_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/nanite_mesh - id = "nanite_mesh" - display_name = "Mesh Nanite Programming" - description = "Nanite programs that require static structures and membranes." - prereq_ids = list("nanite_base","engineering") - design_ids = list("hardening_nanites", "dermal_button_nanites", "refractive_nanites", "cryo_nanites", "conductive_nanites", "shock_nanites", "emp_nanites", "temperature_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/nanite_bio - id = "nanite_bio" - display_name = "Biological Nanite Programming" - description = "Nanite programs that require complex biological interaction." - prereq_ids = list("nanite_base","biotech") - design_ids = list("regenerative_nanites", "bloodheal_nanites", "coagulating_nanites","poison_nanites","flesheating_nanites",\ - "sensor_crit_nanites","sensor_death_nanites", "sensor_health_nanites", "sensor_damage_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/nanite_neural - id = "nanite_neural" - display_name = "Neural Nanite Programming" - description = "Nanite programs affecting nerves and brain matter." - prereq_ids = list("nanite_bio") - design_ids = list("nervous_nanites", "brainheal_nanites", "paralyzing_nanites", "stun_nanites", "selfscan_nanites","good_mood_nanites","bad_mood_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/nanite_synaptic - id = "nanite_synaptic" - display_name = "Synaptic Nanite Programming" - description = "Nanite programs affecting mind and thoughts." - prereq_ids = list("nanite_neural","neural_programming") - design_ids = list("mindshield_nanites", "pacifying_nanites", "blinding_nanites", "sleep_nanites", "mute_nanites", "speech_nanites","hallucination_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/nanite_harmonic - id = "nanite_harmonic" - display_name = "Harmonic Nanite Programming" - description = "Nanite programs that require seamless integration between nanites and biology." - prereq_ids = list("nanite_bio","nanite_smart","nanite_mesh") - design_ids = list("fakedeath_nanites","researchplus_nanites","aggressive_nanites","defib_nanites","regenerative_plus_nanites","brainheal_plus_nanites","purging_plus_nanites","adrenaline_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) - -/datum/techweb_node/nanite_combat - id = "nanite_military" - display_name = "Military Nanite Programming" - description = "Nanite programs that perform military-grade functions." - prereq_ids = list("nanite_harmonic", "syndicate_basic") - design_ids = list("explosive_nanites","pyro_nanites","meltdown_nanites","viral_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) - -/datum/techweb_node/nanite_hazard - id = "nanite_hazard" - display_name = "Hazard Nanite Programs" - description = "Extremely advanced Nanite programs with the potential of being extremely dangerous." - prereq_ids = list("nanite_harmonic", "alientech") - design_ids = list("spreading_nanites","mindcontrol_nanites","mitosis_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - -/datum/techweb_node/nanite_replication_protocols - id = "nanite_replication_protocols" - display_name = "Nanite Replication Protocols" - description = "Advanced behaviours that allow nanites to exploit certain circumstances to replicate faster." - prereq_ids = list("nanite_smart") - design_ids = list("kickstart_nanites","factory_nanites","tinker_nanites","offline_nanites","synergy_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - -////////////////////////Alien technology//////////////////////// -/datum/techweb_node/alientech //AYYYYYYYYLMAOO tech - id = "alientech" - display_name = "Alien Technology" - description = "Things used by the greys." - prereq_ids = list("biotech","engineering") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - hidden = TRUE - design_ids = list("alienalloy") - -/datum/techweb_node/alientech/New() - . = ..() - boost_item_paths = typesof(/obj/item/gun/energy/alien, /obj/item/scalpel/alien, /obj/item/hemostat/alien, - /obj/item/retractor/alien, /obj/item/circular_saw/alien, /obj/item/cautery/alien, - /obj/item/surgicaldrill/alien, /obj/item/screwdriver/abductor, /obj/item/wrench/abductor, - /obj/item/crowbar/abductor, /obj/item/multitool/abductor, - /obj/item/stock_parts/cell/infinite/abductor, /obj/item/weldingtool/abductor, - /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, - /obj/item/abductor, /obj/item/stack/sheet/mineral/abductor) - -/datum/techweb_node/alien_bio - id = "alien_bio" - display_name = "Alien Biological Tools" - description = "Advanced biological tools." - prereq_ids = list("alientech", "advance_surgerytools") - design_ids = list("alien_scalpel", "alien_hemostat", "alien_retractor", "alien_saw", "alien_drill", "alien_cautery", "ayyplantgenes") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - -/datum/techweb_node/alien_engi - id = "alien_engi" - display_name = "Alien Engineering" - description = "Alien engineering tools." - prereq_ids = list("alientech", "exp_tools") - design_ids = list("alien_wrench", "alien_wirecutters", "alien_screwdriver", "alien_crowbar", "alien_welder", "alien_multitool") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - -/datum/techweb_node/syndicate_basic - id = "syndicate_basic" - display_name = "Illegal Technology" - description = "Dangerous research used to create dangerous objects." - prereq_ids = list("adv_engi", "adv_weaponry", "explosive_weapons") - design_ids = list("decloner", "borg_syndicate_module", "suppressor", "largecrossbow", "donksofttoyvendor", "donksoft_refill", "syndiesleeper") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - hidden = TRUE - -/datum/techweb_node/syndicate_basic/New() //Crappy way of making syndicate gear decon supported until there's another way. - . = ..() - boost_item_paths = list() - for(var/path in GLOB.uplink_items) - var/datum/uplink_item/UI = new path - if(!UI.item || !UI.illegal_tech) - continue - boost_item_paths |= UI.item //allows deconning to unlock. - -/datum/techweb_node/advanced_illegal_ballistics - id = "advanced_illegal_ballistics" - display_name = "Advanced Non-Standard Ballistics" - description = "Ballistic ammunition for non-standard firearms. Usually the ones you don't have nor want to be involved with." - design_ids = list("10mm","10mmap","10mminc","10mmhp","sl357","sl357ap","pistolm9mm","m45","bolt_clip") - prereq_ids = list("ballistic_weapons","syndicate_basic","explosive_weapons") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 25000) //This gives sec lethal mags/clips for guns from traitors, space, or anything in between. - -//Helpers for debugging/balancing the techweb in its entirety! - -/proc/total_techweb_points() - var/list/datum/techweb_node/processing = list() - for(var/i in subtypesof(/datum/techweb_node)) - processing += new i - var/datum/techweb/TW = new - TW.research_points = list() - for(var/i in processing) - var/datum/techweb_node/TN = i - TW.add_point_list(TN.research_costs) - return TW.research_points - -/proc/total_techweb_points_printout() - var/list/datum/techweb_node/processing = list() - for(var/i in subtypesof(/datum/techweb_node)) - processing += new i - var/datum/techweb/TW = new - TW.research_points = list() - for(var/i in processing) - var/datum/techweb_node/TN = i - TW.add_point_list(TN.research_costs) - return TW.printout_points() diff --git a/code/modules/research/techweb/nodes/alien_nodes.dm b/code/modules/research/techweb/nodes/alien_nodes.dm new file mode 100644 index 0000000000..567a5dbded --- /dev/null +++ b/code/modules/research/techweb/nodes/alien_nodes.dm @@ -0,0 +1,36 @@ + +////////////////////////Alien technology//////////////////////// +/datum/techweb_node/alientech //AYYYYYYYYLMAOO tech + id = "alientech" + display_name = "Alien Technology" + description = "Things used by the greys." + prereq_ids = list("biotech","engineering") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + hidden = TRUE + design_ids = list("alienalloy") + +/datum/techweb_node/alientech/New() + . = ..() + boost_item_paths = typesof(/obj/item/gun/energy/alien, /obj/item/scalpel/alien, /obj/item/hemostat/alien, + /obj/item/retractor/alien, /obj/item/circular_saw/alien, /obj/item/cautery/alien, + /obj/item/surgicaldrill/alien, /obj/item/screwdriver/abductor, /obj/item/wrench/abductor, + /obj/item/crowbar/abductor, /obj/item/multitool/abductor, + /obj/item/stock_parts/cell/infinite/abductor, /obj/item/weldingtool/abductor, + /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, + /obj/item/abductor, /obj/item/stack/sheet/mineral/abductor) + +/datum/techweb_node/alien_bio + id = "alien_bio" + display_name = "Alien Biological Tools" + description = "Advanced biological tools." + prereq_ids = list("alientech", "advance_surgerytools") + design_ids = list("alien_scalpel", "alien_hemostat", "alien_retractor", "alien_saw", "alien_drill", "alien_cautery", "ayyplantgenes") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + +/datum/techweb_node/alien_engi + id = "alien_engi" + display_name = "Alien Engineering" + description = "Alien engineering tools." + prereq_ids = list("alientech", "exp_tools") + design_ids = list("alien_wrench", "alien_wirecutters", "alien_screwdriver", "alien_crowbar", "alien_welder", "alien_multitool") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) diff --git a/code/modules/research/techweb/nodes/bepis_nodes.dm b/code/modules/research/techweb/nodes/bepis_nodes.dm new file mode 100644 index 0000000000..0033564274 --- /dev/null +++ b/code/modules/research/techweb/nodes/bepis_nodes.dm @@ -0,0 +1,82 @@ +////////////////////////B.E.P.I.S. Locked Techs//////////////////////// + +/datum/techweb_node/light_apps + id = "light_apps" + display_name = "Illumination Applications" + description = "Applications of lighting and vision technology not originally thought to be commercially viable." + prereq_ids = list("base") + design_ids = list("bright_helmet", "rld_mini") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/aus_security + id = "aus_security" + display_name = "Australicus Security Protocols" + description = "It is said that security in the Australicus sector is tight, so we took some pointers from their equipment. Thankfully, our sector lacks any signs of these, 'dropbears'." + prereq_ids = list("base") + design_ids = list("pin_explorer", "stun_boomerang") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/spec_eng + id = "spec_eng" + display_name = "Specialized Engineering" + description = "Conventional wisdom has deemed these engineering products 'technically' safe, but far too dangerous to traditionally condone." + prereq_ids = list("base") + design_ids = list("lava_rods", "eng_gloves") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/rolling_table + id = "rolling_table" + display_name = "Advanced Wheel Applications" + description = "Adding wheels to things can lead to extremely beneficial outcomes." + prereq_ids = list("base") + design_ids = list("rolling_table") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/Mauna_Mug + id = "mauna_mug" + display_name = "Mauna Mug" + description = "A bored scientist was thinking to himself for very long...and then realized his coffee got cold! He made this invention to solve this extreme problem." + prereq_ids = list("base") + design_ids = list("mauna_mug") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/nanite_replication_protocols + id = "nanite_replication_protocols" + display_name = "Nanite Replication Protocols" + description = "Advanced behaviours that allow nanites to exploit certain circumstances to replicate faster." + prereq_ids = list("nanite_smart") + design_ids = list("kickstart_nanites","factory_nanites","tinker_nanites","offline_nanites","synergy_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/interrogation + id = "interrogation" + display_name = "Enhanced Interrogation Technology" + description = "By cross-referencing several declassified documents from past dictatorial regimes, we were able to develop an incredibly effective interrogation device. \ + Ethical concerns about loss of free will may still apply, according to galactic law." + prereq_ids = list("base") + design_ids = list("hypnochair") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/tackle_advanced + id = "tackle_advanced" + display_name = "Advanced Grapple Technology" + description = "Nanotrasen would like to remind its researching staff that it is never acceptable to \"glomp\" your coworkers, and further \"scientific trials\" on the subject \ + will no longer be accepted in its academic journals." + design_ids = list("tackle_dolphin", "tackle_rocket") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + hidden = TRUE + experimental = TRUE diff --git a/code/modules/research/techweb/nodes/biotech_nodes.dm b/code/modules/research/techweb/nodes/biotech_nodes.dm new file mode 100644 index 0000000000..8f7d978a99 --- /dev/null +++ b/code/modules/research/techweb/nodes/biotech_nodes.dm @@ -0,0 +1,25 @@ + +/////////////////////////Biotech///////////////////////// +/datum/techweb_node/biotech + id = "biotech" + display_name = "Biological Technology" + description = "What makes us tick." //the MC, silly! + prereq_ids = list("base") + design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibrillator", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen", "telescopiciv", "medspray","genescanner") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/adv_biotech + id = "adv_biotech" + display_name = "Advanced Biotechnology" + description = "Advanced Biotechnology" + prereq_ids = list("biotech") + design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "meta_beaker", "healthanalyzer_advanced", "harvester", "holobarrier_med", "defibrillator_compact", "smartdartgun", "medicinalsmartdart", "pHmeter", "containmentbodybag") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/bio_process + id = "bio_process" + display_name = "Biological Processing" + description = "From slimes to kitchens." + prereq_ids = list("biotech") + design_ids = list("smartfridge", "gibber", "deepfryer", "monkey_recycler", "processor", "gibber", "microwave", "reagentgrinder", "dish_drive") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) diff --git a/code/modules/research/techweb/nodes/bluespace_nodes.dm b/code/modules/research/techweb/nodes/bluespace_nodes.dm new file mode 100644 index 0000000000..85142cd9b8 --- /dev/null +++ b/code/modules/research/techweb/nodes/bluespace_nodes.dm @@ -0,0 +1,65 @@ + +/////////////////////////Bluespace tech///////////////////////// +/datum/techweb_node/bluespace_basic //Bluespace-memery + id = "bluespace_basic" + display_name = "Basic Bluespace Theory" + description = "Basic studies into the mysterious alternate dimension known as bluespace." + prereq_ids = list("base", "datatheory") + design_ids = list("beacon", "xenobioconsole", "telesci_gps", "xenobio_monkeys") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/practical_bluespace + id = "practical_bluespace" + display_name = "Applied Bluespace Research" + description = "Using bluespace to make things faster and better." + prereq_ids = list("bluespace_basic", "engineering") + design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + +/datum/techweb_node/adv_bluespace + id = "adv_bluespace" + display_name = "Advanced Bluespace Research" + description = "Deeper understanding of how the Bluespace dimension works" + prereq_ids = list("practical_bluespace", "high_efficiency") + design_ids = list("bluespace_matter_bin", "femto_mani", "triphasic_scanning", "bluespace_crystal", "xenobio_slimeadv") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) + +/datum/techweb_node/bluespace_power + id = "bluespace_power" + display_name = "Bluespace Power Technology" + description = "Even more powerful.. power!" + prereq_ids = list("adv_power", "adv_bluespace") + design_ids = list("bluespace_cell", "quadratic_capacitor") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/bluespace_holding + id = "bluespace_holding" + display_name = "Bluespace Pockets" + description = "Studies into the mysterious alternate dimension known as bluespace and how to place items in the threads of reality." + prereq_ids = list("adv_power", "adv_bluespace", "adv_biotech", "adv_plasma") + design_ids = list( "bluespacebodybag","bag_holding", "bluespace_pod", "borg_upgrade_trashofholding", "blutrash", "satchel_holding", "bsblood_bag", "duffelbag_holding") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5500) + +/datum/techweb_node/bluespace_portal + id = "bluespace_portal" + display_name = "Bluespace Portals" + description = "Allows for Bluespace Tech to be used tandem with Wormhole tech." + prereq_ids = list("adv_weaponry", "adv_bluespace") + design_ids = list("wormholeprojector") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/bluespace_warping + id = "bluespace_warping" + display_name = "Bluespace Travel" + description = "Application of Bluespace for static teleportation technology." + prereq_ids = list("adv_power", "adv_bluespace") + design_ids = list("tele_station", "tele_hub", "quantumpad", "quantum_keycard", "launchpad", "launchpad_console", "teleconsole", "roastingstick") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/unregulated_bluespace + id = "unregulated_bluespace" + display_name = "Unregulated Bluespace Research" + description = "Bluespace technology using unstable or unbalanced procedures, prone to damaging the fabric of bluespace. Outlawed by galactic conventions." + prereq_ids = list("bluespace_warping", "syndicate_basic") + design_ids = list("desynchronizer") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) diff --git a/code/modules/research/techweb/nodes/computer_hud_nodes.dm b/code/modules/research/techweb/nodes/computer_hud_nodes.dm new file mode 100644 index 0000000000..2835edc52b --- /dev/null +++ b/code/modules/research/techweb/nodes/computer_hud_nodes.dm @@ -0,0 +1,60 @@ + +////////////////////////Computer tech//////////////////////// +/datum/techweb_node/comptech + id = "comptech" + display_name = "Computer Consoles" + description = "Computers and how they work." + prereq_ids = list("datatheory") + design_ids = list("cargo", "cargorequest", "libraryconsole", "mining", "miningshuttle", "crewconsole", "rdcamera", "comconsole", "idcardconsole", "seccamera") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + +/datum/techweb_node/computer_hardware_basic //Modular computers are shitty and nearly useless so until someone makes them actually useful this can be easy to get. + id = "computer_hardware_basic" + display_name = "Computer Hardware" + description = "How computer hardware are made." + prereq_ids = list("comptech") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) //they are really kinda shitty + design_ids = list("hdd_basic", "hdd_advanced", "hdd_super", "hdd_cluster", "ssd_small", "ssd_micro", "netcard_basic", "netcard_advanced", "netcard_wired", + "portadrive_basic", "portadrive_advanced", "portadrive_super", "cardslot", "aislot", "miniprinter", "APClink", "bat_control", "bat_normal", "bat_advanced", + "bat_super", "bat_micro", "bat_nano", "cpu_normal", "pcpu_normal", "cpu_small", "pcpu_small") + +/datum/techweb_node/comp_recordkeeping + id = "comp_recordkeeping" + display_name = "Computerized Recordkeeping" + description = "Organized record databases and how they're used." + prereq_ids = list("comptech") + design_ids = list("secdata", "med_data", "prisonmanage", "vendor", "automated_announcement") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) + +/datum/techweb_node/telecomms + id = "telecomms" + display_name = "Telecommunications Technology" + description = "Subspace transmission technology for near-instant communications devices." + prereq_ids = list("comptech", "bluespace_basic") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) + design_ids = list("s-receiver", "s-bus", "s-broadcaster", "s-processor", "s-hub", "s-server", "s-relay", "comm_monitor", "comm_server", + "s-ansible", "s-filter", "s-amplifier", "ntnet_relay", "s-treatment", "s-analyzer", "s-crystal", "s-transmitter", "message_monitor") + +/datum/techweb_node/integrated_HUDs + id = "integrated_HUDs" + display_name = "Integrated HUDs" + description = "The usefulness of computerized records, projected straight onto your eyepiece!" + prereq_ids = list("comp_recordkeeping", "emp_basic") + design_ids = list("health_hud", "security_hud", "diagnostic_hud", "scigoggles", "health_hud_prescription", "security_hud_prescription", "diagnostic_hud_prescription") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) + +/datum/techweb_node/NVGtech + id = "NVGtech" + display_name = "Night Vision Technology" + description = "Allows seeing in the dark without actual light!" + prereq_ids = list("integrated_HUDs", "adv_engi", "emp_adv") + design_ids = list("health_hud_night", "security_hud_night", "diagnostic_hud_night", "night_visision_goggles", "nvgmesons", "night_visision_goggles_glasses") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + +/datum/techweb_node/computer_board_gaming + id = "computer_board_gaming" + display_name = "Games and Toys" + description = "For the slackers on the station." + prereq_ids = list("comptech") + design_ids = list("arcade_battle", "arcade_orion", "arcade_minesweeper", "slotmachine", "autoylathe") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) diff --git a/code/modules/research/techweb/nodes/engineering_nodes.dm b/code/modules/research/techweb/nodes/engineering_nodes.dm new file mode 100644 index 0000000000..2ab5458028 --- /dev/null +++ b/code/modules/research/techweb/nodes/engineering_nodes.dm @@ -0,0 +1,59 @@ + +/////////////////////////engineering tech///////////////////////// +/datum/techweb_node/engineering + id = "engineering" + display_name = "Industrial Engineering" + description = "A refresher course on modern engineering technology." + prereq_ids = list("base") + design_ids = list("solarcontrol", "recharger", "powermonitor", "rped", "pacman", "adv_capacitor", "adv_scanning", "emitter", "high_cell", "adv_matter_bin", + "atmosalerts", "atmos_control", "recycler", "autolathe", "autolathe_secure", "high_micro_laser", "nano_mani", "mesons", "thermomachine", "rad_collector", "tesla_coil", "grounding_rod", + "apc_control", "power control", "airlock_board", "firelock_board", "airalarm_electronics", "firealarm_electronics", "cell_charger", "stack_console", "stack_machine", "rcd_ammo") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 6000) + +/datum/techweb_node/adv_engi + id = "adv_engi" + display_name = "Advanced Engineering" + description = "Pushing the boundaries of physics, one chainsaw-fist at a time." + prereq_ids = list("engineering", "emp_basic") + design_ids = list("engine_goggles", "magboots", "forcefield_projector", "weldingmask" , "rcd_loaded", "rpd", "tray_goggles_prescription", "engine_goggles_prescription", "mesons_prescription", "rcd_upgrade_frames", "rcd_upgrade_simple_circuits", "rcd_ammo_large") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) + +/datum/techweb_node/anomaly + id = "anomaly_research" + display_name = "Anomaly Research" + description = "Unlock the potential of the mysterious anomalies that appear on station." + prereq_ids = list("adv_engi", "practical_bluespace") + design_ids = list("reactive_armour", "anomaly_neutralizer") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) + +/datum/techweb_node/high_efficiency + id = "high_efficiency" + display_name = "High Efficiency Parts" + description = "Finely-tooled manufacturing techniques allowing for picometer-perfect precision levels." + prereq_ids = list("engineering", "datatheory") + design_ids = list("pico_mani", "super_matter_bin") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + +/datum/techweb_node/adv_power + id = "adv_power" + display_name = "Advanced Power Manipulation" + description = "How to get more zap." + prereq_ids = list("engineering") + design_ids = list("smes", "super_cell", "hyper_cell", "super_capacitor", "superpacman", "mrspacman", "power_turbine", "power_turbine_console", "power_compressor", "circulator", "teg") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) + +/* +/datum/techweb_node/basic_meteor_defense + id = "basic_meteor_defense" + display_name = "Meteor Defense Research" + description = "Unlock the potential of the mysterious of why CC decided to not build these around the station themselves." + prereq_ids = list("adv_engi", "high_efficiency") + design_ids = list("meteor_defence", "meteor_console") + +/datum/techweb_node/adv_meteor_defense + id = "adv_meteor_defense" + display_name = "Meteor Defense Research" + description = "New and improved coding and lock on tech for meteor defence!" + prereq_ids = list("basic_meteor_defense", "adv_datatheory", "emp_adv") + design_ids = list("meteor_disk") +*/ diff --git a/code/modules/research/techweb/nodes/export_nodes.dm b/code/modules/research/techweb/nodes/export_nodes.dm new file mode 100644 index 0000000000..cbdedef113 --- /dev/null +++ b/code/modules/research/techweb/nodes/export_nodes.dm @@ -0,0 +1,21 @@ +/datum/techweb_node/blueprinted_bottles + id = "blueprinted_bottles" + display_name = "License Bottling" + description = "Some Branded bottles to print and export." + starting_node = TRUE + design_ids = list("gin", "wine", "whiskey", "vodka", "tequila", "patron", "rum", "kahlua", "vermouth", "goldschlager", "hcider", "cognac", "absinthe", "grappa", "sake", "fernet", "applejack", "champagne", "blazaam", "trappist", "grenadine", "autobottler") + +/datum/techweb_node/blueprinted_exports + id = "blueprinted_exports" + display_name = "License Exports" + description = "Some Branded bottles to print and export." + starting_node = TRUE + design_ids = list("gin_export", "wine_export", "whiskey_export", "vodka_export", "tequila_export", "patron_export", "rum_export", "kahlua_export", "vermouth_export", "goldschlager_export", "hcider_export", "cognac_export", "absinthe_export", "grappa_export", "sake_export", "fernet_export", "applejack_export", "champagne_export", "blazaam_export", "trappist_export", "grenadine_export") + +/datum/techweb_node/bottle_exports + id = "bottle_exports" + display_name = "Legal Bottling" + prereq_ids = list("blueprinted_bottles") + description = "New bottles for printing and selling." + design_ids = list("minikeg", "blooddrop", "slim_gold", "white_bloodmoon", "greenroad") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 250) diff --git a/code/modules/research/techweb/nodes/mecha_nodes.dm b/code/modules/research/techweb/nodes/mecha_nodes.dm new file mode 100644 index 0000000000..4d1b703cae --- /dev/null +++ b/code/modules/research/techweb/nodes/mecha_nodes.dm @@ -0,0 +1,205 @@ + +////////////////////////mech technology//////////////////////// + +/datum/techweb_node/mech + id = "mecha" + starting_node = TRUE + display_name = "Mechanical Exosuits" + description = "Mechanized exosuits that are several magnitudes stronger and more powerful than the average human." + design_ids = list("mecha_tracking", "mechacontrol", "mechapower", "mech_recharger", "ripley_chassis", "firefighter_chassis", "ripley_torso", "ripley_left_arm", "ripley_right_arm", "ripley_left_leg", "ripley_right_leg", + "ripley_main", "ripley_peri", "mech_hydraulic_clamp") + +/datum/techweb_node/mech_tools + id = "mech_tools" + starting_node = TRUE + display_name = "Basic Exosuit Equipment" + description = "Various tools fit for basic mech units" + design_ids = list("mech_drill", "mech_mscanner", "mech_extinguisher", "mech_cable_layer") + +/datum/techweb_node/adv_mecha + id = "adv_mecha" + display_name = "Advanced Exosuits" + description = "For when you just aren't Gundam enough." + prereq_ids = list("adv_robotics") + design_ids = list("mech_repair_droid") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/odysseus + id = "mecha_odysseus" + display_name = "EXOSUIT: Odysseus" + description = "Odysseus exosuit designs" + prereq_ids = list("base") + design_ids = list("odysseus_chassis", "odysseus_torso", "odysseus_head", "odysseus_left_arm", "odysseus_right_arm" ,"odysseus_left_leg", "odysseus_right_leg", + "odysseus_main", "odysseus_peri") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/gygax + id = "mech_gygax" + display_name = "EXOSUIT: Gygax" + description = "Gygax exosuit designs" + prereq_ids = list("adv_mecha", "weaponry") + design_ids = list("gygax_chassis", "gygax_torso", "gygax_head", "gygax_left_arm", "gygax_right_arm", "gygax_left_leg", "gygax_right_leg", "gygax_main", + "gygax_peri", "gygax_targ", "gygax_armor") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/durand + id = "mech_durand" + display_name = "EXOSUIT: Durand" + description = "Durand exosuit designs" + prereq_ids = list("adv_mecha", "adv_weaponry") + design_ids = list("durand_chassis", "durand_torso", "durand_head", "durand_left_arm", "durand_right_arm", "durand_left_leg", "durand_right_leg", "durand_main", + "durand_peri", "durand_targ", "durand_armor") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) + +/datum/techweb_node/phazon + id = "mecha_phazon" + display_name = "EXOSUIT: Phazon" + description = "Phazon exosuit designs" + prereq_ids = list("adv_mecha", "weaponry" , "adv_bluespace") + design_ids = list("phazon_chassis", "phazon_torso", "phazon_head", "phazon_left_arm", "phazon_right_arm", "phazon_left_leg", "phazon_right_leg", "phazon_main", + "phazon_peri", "phazon_targ", "phazon_armor") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) + +/datum/techweb_node/adv_mecha_tools + id = "adv_mecha_tools" + display_name = "Advanced Exosuit Equipment" + description = "Tools for high level mech suits" + prereq_ids = list("adv_mecha") + design_ids = list("mech_rcd") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/med_mech_tools + id = "med_mech_tools" + display_name = "Medical Exosuit Equipment" + description = "Tools for high level mech suits" + prereq_ids = list("adv_biotech") + design_ids = list("mech_sleeper", "mech_syringe_gun", "mech_medi_beam") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + +/datum/techweb_node/mech_modules + id = "adv_mecha_modules" + display_name = "Simple Exosuit Modules" + description = "An advanced piece of mech weaponry" + prereq_ids = list("adv_mecha", "bluespace_power") + design_ids = list("mech_energy_relay", "mech_ccw_armor", "mech_proj_armor", "mech_generator_nuclear") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/mech_scattershot + id = "mecha_tools" + display_name = "Exosuit Weapon (LBX AC 10 \"Scattershot\")" + description = "An advanced piece of mech weaponry" + prereq_ids = list("ballistic_weapons") + design_ids = list("mech_scattershot", "mech_scattershot_ammo") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/mech_seedscatter + id = "mech_seedscatter" + display_name = "Exosuit Weapon (Melon Seed \"Scattershot\")" + description = "An advanced piece of mech weaponry" + prereq_ids = list("ballistic_weapons") + design_ids = list("mech_seedscatter") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/mech_carbine + id = "mech_carbine" + display_name = "Exosuit Weapon (FNX-99 \"Hades\" Carbine)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("ballistic_weapons") + design_ids = list("mech_carbine", "mech_carbine_ammo") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/mech_ion + id = "mmech_ion" + display_name = "Exosuit Weapon (MKIV Ion Heavy Cannon)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("electronic_weapons", "emp_adv") + design_ids = list("mech_ion") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/mech_tesla + id = "mech_tesla" + display_name = "Exosuit Weapon (MKI Tesla Cannon)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("electronic_weapons", "adv_power") + design_ids = list("mech_tesla") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/mech_laser + id = "mech_laser" + display_name = "Exosuit Weapon (CH-PS \"Immolator\" Laser)" + description = "A basic piece of mech weaponry" + prereq_ids = list("beam_weapons") + design_ids = list("mech_laser") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/mech_laser_heavy + id = "mech_laser_heavy" + display_name = "Exosuit Weapon (CH-LC \"Solaris\" Laser Cannon)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("adv_beam_weapons") + design_ids = list("mech_laser_heavy") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/mech_grenade_launcher + id = "mech_grenade_launcher" + display_name = "Exosuit Weapon (SGL-6 Grenade Launcher)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("explosive_weapons") + design_ids = list("mech_grenade_launcher", "mech_grenade_launcher_ammo") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/mech_missile_rack + id = "mech_missile_rack" + display_name = "Exosuit Weapon (BRM-6 Missile Rack)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("explosive_weapons") + design_ids = list("mech_missile_rack", "mech_missile_rack_ammo") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/clusterbang_launcher + id = "clusterbang_launcher" + display_name = "Exosuit Module (SOB-3 Clusterbang Launcher)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("explosive_weapons") + design_ids = list("clusterbang_launcher", "clusterbang_launcher_ammo") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/mech_teleporter + id = "mech_teleporter" + display_name = "Exosuit Module (Teleporter Module)" + description = "An advanced piece of mech Equipment" + prereq_ids = list("adv_bluespace") + design_ids = list("mech_teleporter") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/mech_wormhole_gen + id = "mech_wormhole_gen" + display_name = "Exosuit Module (Localized Wormhole Generator)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("adv_bluespace") + design_ids = list("mech_wormhole_gen") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/mech_taser + id = "mech_taser" + display_name = "Exosuit Weapon (PBT \"Pacifier\" Mounted Taser)" + description = "A basic piece of mech weaponry" + prereq_ids = list("electronic_weapons") + design_ids = list("mech_taser") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/mech_lmg + id = "mech_lmg" + display_name = "Exosuit Weapon (\"Ultra AC 2\" LMG)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("ballistic_weapons") + design_ids = list("mech_lmg", "mech_lmg_ammo") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/mech_diamond_drill + id = "mech_diamond_drill" + display_name = "Exosuit Diamond Drill" + description = "A diamond drill fit for a large exosuit" + prereq_ids = list("adv_mining") + design_ids = list("mech_diamond_drill") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) diff --git a/code/modules/research/techweb/nodes/medical_nodes.dm b/code/modules/research/techweb/nodes/medical_nodes.dm new file mode 100644 index 0000000000..71dd7c943c --- /dev/null +++ b/code/modules/research/techweb/nodes/medical_nodes.dm @@ -0,0 +1,132 @@ + +////////////////////////Medical//////////////////////// +/datum/techweb_node/cloning + id = "cloning" + display_name = "Genetic Engineering" + description = "We have the technology to make him." + prereq_ids = list("biotech") + design_ids = list("clonecontrol", "clonepod", "clonescanner", "scan_console", "cloning_disk") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + +/datum/techweb_node/cryotech + id = "cryotech" + display_name = "Cryostasis Technology" + description = "Smart freezing of objects to preserve them!" + prereq_ids = list("adv_engi", "biotech") + design_ids = list("splitbeaker", "noreactsyringe", "cryotube", "cryo_Grenade") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + +/datum/techweb_node/adv_defibrillator_tec + id = "adv_defibrillator_tec" + display_name = "Defibrillator Upgrades" + description = "More ways to bring back the newly dead." + prereq_ids = list("adv_biotech", "exp_surgery", "adv_engi", "adv_power") + design_ids = list("defib_decay", "defib_shock", "defib_heal", "defib_speed") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +//////////////////////Cybernetics///////////////////// + +/datum/techweb_node/surplus_limbs + id = "surplus_limbs" + display_name = "Basic Prosthetics" + description = "Basic fragile prosthetics for the impaired." + starting_node = TRUE + prereq_ids = list("biotech") + design_ids = list("basic_l_arm", "basic_r_arm", "basic_r_leg", "basic_l_leg") + +/datum/techweb_node/advance_limbs + id = "advance_limbs" + display_name = "Upgraded Prosthetics" + description = "Reinforced prosthetics for the impaired." + prereq_ids = list("adv_biotech", "surplus_limbs") + design_ids = list("adv_l_arm", "adv_r_arm", "adv_r_leg", "adv_l_leg") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) + +/datum/techweb_node/subdermal_implants + id = "subdermal_implants" + display_name = "Subdermal Implants" + description = "Electronic implants buried beneath the skin." + prereq_ids = list("biotech", "datatheory") + design_ids = list("implanter", "implantcase", "implant_chem", "implant_tracking", "locator", "c38_trac") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/cyber_organs + id = "cyber_organs" + display_name = "Cybernetic Organs" + description = "We have the technology to rebuild him." + prereq_ids = list("adv_biotech") + design_ids = list("cybernetic_ears", "cybernetic_heart", "cybernetic_liver", "cybernetic_lungs", "cybernetic_tongue") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) + +/datum/techweb_node/cyber_organs_upgraded + id = "cyber_organs_upgraded" + display_name = "Upgraded Cybernetic Organs" + description = "We have the technology to upgrade him." + prereq_ids = list("cyber_organs") + design_ids = list("cybernetic_ears_u", "cybernetic_heart_u", "cybernetic_liver_u", "cybernetic_lungs_u") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) + +/datum/techweb_node/cyber_implants + id = "cyber_implants" + display_name = "Cybernetic Implants" + description = "Electronic implants that improve humans." + prereq_ids = list("adv_biotech", "adv_datatheory") + design_ids = list("ci-nutriment", "ci-breather", "ci-gloweyes", "ci-welding", "ci-medhud", "ci-sechud", "ci-service") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/adv_cyber_implants + id = "adv_cyber_implants" + display_name = "Advanced Cybernetic Implants" + description = "Upgraded and more powerful cybernetic implants." + prereq_ids = list("neural_programming", "cyber_implants","integrated_HUDs") + design_ids = list("ci-toolset", "ci-surgery", "ci-reviver", "ci-nutrimentplus") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/combat_cyber_implants + id = "combat_cyber_implants" + display_name = "Combat Cybernetic Implants" + description = "Military grade combat implants to improve performance." + prereq_ids = list("adv_cyber_implants","weaponry","NVGtech","high_efficiency") + design_ids = list("ci-xray", "ci-thermals", "ci-antidrop", "ci-antistun", "ci-thrusters", "ci-shield") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/////////////////////////Advanced Surgery///////////////////////// +/datum/techweb_node/imp_wt_surgery + id = "imp_wt_surgery" + display_name = "Improved Wound-Tending Surgery" + description = "Who would have known being more gentle with a hemostat decreases patient pain?" + prereq_ids = list("biotech") + design_ids = list("surgery_heal_brute_upgrade","surgery_heal_burn_upgrade") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) + +/datum/techweb_node/advance_surgerytools + id = "advance_surgerytools" + display_name = "Advanced Surgery Tools" + description = "Refined and improved redesigns for the run-of-the-mill medical utensils." + prereq_ids = list("adv_biotech", "adv_surgery") + design_ids = list("drapes", "retractor_adv", "surgicaldrill_adv", "scalpel_adv") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/adv_surgery + id = "adv_surgery" + display_name = "Advanced Surgery" + description = "When simple medicine doesn't cut it." + prereq_ids = list("imp_wt_surgery") + design_ids = list("surgery_revival", "surgery_lobotomy", "surgery_heal_brute_upgrade_femto","surgery_heal_burn_upgrade_femto", "surgery_heal_combo", "surgery_toxinhealing", "organbox", "surgery_adv_dissection") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/exp_surgery + id = "exp_surgery" + display_name = "Experimental Surgery" + description = "When evolution isn't fast enough." + prereq_ids = list("adv_surgery") + design_ids = list("surgery_pacify","surgery_vein_thread","surgery_muscled_veins","surgery_nerve_splice","surgery_nerve_ground","surgery_ligament_hook","surgery_ligament_reinforcement","surgery_viral_bond", "surgery_exp_dissection", "surgery_heal_combo_upgrade") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + +/datum/techweb_node/alien_surgery + id = "alien_surgery" + display_name = "Alien Surgery" + description = "Abductors did nothing wrong." + prereq_ids = list("exp_surgery", "alientech") + design_ids = list("surgery_brainwashing","surgery_zombie", "surgery_ext_dissection", "surgery_heal_combo_upgrade_femto") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) diff --git a/code/modules/research/techweb/nodes/misc_nodes.dm b/code/modules/research/techweb/nodes/misc_nodes.dm new file mode 100644 index 0000000000..d34afca90a --- /dev/null +++ b/code/modules/research/techweb/nodes/misc_nodes.dm @@ -0,0 +1,68 @@ + +/////////////////////////data theory tech///////////////////////// +/datum/techweb_node/datatheory //Computer science + id = "datatheory" + display_name = "Data Theory" + description = "Big Data, in space!" + prereq_ids = list("base") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + +/datum/techweb_node/adv_datatheory + id = "adv_datatheory" + display_name = "Advanced Data Theory" + description = "Better insight into programming and data." + prereq_ids = list("datatheory") + design_ids = list("icprinter", "icupgadv", "icupgclo") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) + +/////////////////////////plasma tech///////////////////////// +/datum/techweb_node/basic_plasma + id = "basic_plasma" + display_name = "Basic Plasma Research" + description = "Research into the mysterious and dangerous substance, plasma." + prereq_ids = list("engineering") + design_ids = list("mech_generator") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + +/datum/techweb_node/adv_plasma + id = "adv_plasma" + display_name = "Advanced Plasma Research" + description = "Research on how to fully exploit the power of plasma." + prereq_ids = list("basic_plasma") + design_ids = list("mech_plasma_cutter") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) + +/////////////////////////EMP tech///////////////////////// +/datum/techweb_node/emp_basic //EMP tech for some reason + id = "emp_basic" + display_name = "Electromagnetic Theory" + description = "Study into usage of frequencies in the electromagnetic spectrum." + prereq_ids = list("base") + design_ids = list("holosign", "holosignsec", "holosignengi", "holosignatmos", "holosignfirelock", "inducer", "tray_goggles", "holopad") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/emp_adv + id = "emp_adv" + display_name = "Advanced Electromagnetic Theory" + description = "Determining whether reversing the polarity will actually help in a given situation." + prereq_ids = list("emp_basic") + design_ids = list("ultra_micro_laser") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) + +/datum/techweb_node/emp_super + id = "emp_super" + display_name = "Quantum Electromagnetic Technology" //bs + description = "Even better electromagnetic technology." + prereq_ids = list("emp_adv") + design_ids = list("quadultra_micro_laser") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) + +/////////////////////////Clown tech///////////////////////// +/datum/techweb_node/clown + id = "clown" + display_name = "Clown Technology" + description = "Honk?!" + prereq_ids = list("base") + design_ids = list("air_horn", "honker_main", "honker_peri", "honker_targ", "honk_chassis", "honk_head", "honk_torso", "honk_left_arm", "honk_right_arm", + "honk_left_leg", "honk_right_leg", "mech_banana_mortar", "mech_mousetrap_mortar", "mech_honker", "mech_punching_face", "implant_trombone", "borg_transform_clown") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) diff --git a/code/modules/research/techweb/nodes/nanites_nodes.dm b/code/modules/research/techweb/nodes/nanites_nodes.dm new file mode 100644 index 0000000000..0a860c8938 --- /dev/null +++ b/code/modules/research/techweb/nodes/nanites_nodes.dm @@ -0,0 +1,76 @@ + +/////////////////////////Nanites///////////////////////// +/datum/techweb_node/nanite_base + id = "nanite_base" + display_name = "Basic Nanite Programming" + description = "The basics of nanite construction and programming." + prereq_ids = list("datatheory","robotics") + design_ids = list("nanite_disk","nanite_remote","nanite_comm_remote","nanite_scanner",\ + "nanite_chamber","public_nanite_chamber","nanite_chamber_control","nanite_programmer","nanite_program_hub","nanite_cloud_control",\ + "relay_nanites", "monitoring_nanites", "access_nanites", "repairing_nanites","sensor_nanite_volume", "repeater_nanites", "relay_repeater_nanites","red_diag_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/nanite_smart + id = "nanite_smart" + display_name = "Smart Nanite Programming" + description = "Nanite programs that require nanites to perform complex actions, act independently, roam or seek targets." + prereq_ids = list("nanite_base","adv_robotics") + design_ids = list("purging_nanites", "research_nanites", "metabolic_nanites", "stealth_nanites", "memleak_nanites","sensor_voice_nanites", "voice_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + +/datum/techweb_node/nanite_mesh + id = "nanite_mesh" + display_name = "Mesh Nanite Programming" + description = "Nanite programs that require static structures and membranes." + prereq_ids = list("nanite_base","engineering") + design_ids = list("hardening_nanites", "dermal_button_nanites", "refractive_nanites", "cryo_nanites", "conductive_nanites", "shock_nanites", "emp_nanites", "temperature_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/nanite_bio + id = "nanite_bio" + display_name = "Biological Nanite Programming" + description = "Nanite programs that require complex biological interaction." + prereq_ids = list("nanite_base","biotech") + design_ids = list("regenerative_nanites", "bloodheal_nanites", "coagulating_nanites","poison_nanites","flesheating_nanites",\ + "sensor_crit_nanites","sensor_death_nanites", "sensor_health_nanites", "sensor_damage_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/nanite_neural + id = "nanite_neural" + display_name = "Neural Nanite Programming" + description = "Nanite programs affecting nerves and brain matter." + prereq_ids = list("nanite_bio") + design_ids = list("nervous_nanites", "brainheal_nanites", "paralyzing_nanites", "stun_nanites", "selfscan_nanites","good_mood_nanites","bad_mood_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/nanite_synaptic + id = "nanite_synaptic" + display_name = "Synaptic Nanite Programming" + description = "Nanite programs affecting mind and thoughts." + prereq_ids = list("nanite_neural","neural_programming") + design_ids = list("mindshield_nanites", "pacifying_nanites", "blinding_nanites", "sleep_nanites", "mute_nanites", "speech_nanites","hallucination_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/nanite_harmonic + id = "nanite_harmonic" + display_name = "Harmonic Nanite Programming" + description = "Nanite programs that require seamless integration between nanites and biology." + prereq_ids = list("nanite_bio","nanite_smart","nanite_mesh") + design_ids = list("fakedeath_nanites","researchplus_nanites","aggressive_nanites","defib_nanites","regenerative_plus_nanites","brainheal_plus_nanites","purging_plus_nanites","adrenaline_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) + +/datum/techweb_node/nanite_combat + id = "nanite_military" + display_name = "Military Nanite Programming" + description = "Nanite programs that perform military-grade functions." + prereq_ids = list("nanite_harmonic", "syndicate_basic") + design_ids = list("explosive_nanites","pyro_nanites","meltdown_nanites","viral_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) + +/datum/techweb_node/nanite_hazard + id = "nanite_hazard" + display_name = "Hazard Nanite Programs" + description = "Extremely advanced Nanite programs with the potential of being extremely dangerous." + prereq_ids = list("nanite_harmonic", "alientech") + design_ids = list("spreading_nanites","mindcontrol_nanites","mitosis_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) diff --git a/code/modules/research/techweb/nodes/robotics_nodes.dm b/code/modules/research/techweb/nodes/robotics_nodes.dm new file mode 100644 index 0000000000..6248cd99aa --- /dev/null +++ b/code/modules/research/techweb/nodes/robotics_nodes.dm @@ -0,0 +1,81 @@ + +/////////////////////////robotics tech///////////////////////// +/datum/techweb_node/robotics + id = "robotics" + display_name = "Basic Robotics Research" + description = "Programmable machines that make our lives lazier." + prereq_ids = list("base") + design_ids = list("paicard", "drone_shell") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + +/datum/techweb_node/mmi + id = "mmi" + starting_node = TRUE + display_name = "Man Machine Interface" + description = "A slightly Frankensteinian device that allows human brains to interface natively with software APIs." + design_ids = list("mmi") + +/datum/techweb_node/cyborg + id = "cyborg" + starting_node = TRUE + display_name = "Cyborg Construction" + description = "Sapient robots with preloaded tool modules and programmable laws." + design_ids = list("robocontrol", "sflash", "borg_suit", "borg_head", "borg_chest", "borg_r_arm", "borg_l_arm", "borg_r_leg", "borg_l_leg", "borgupload", + "cyborgrecharger", "borg_upgrade_restart", "borg_upgrade_rename") + +/datum/techweb_node/adv_robotics + id = "adv_robotics" + display_name = "Advanced Robotics Research" + description = "It can even do the dishes!" + prereq_ids = list("robotics") + design_ids = list("borg_upgrade_diamonddrill", "borg_upgrade_advancedmop", "borg_upgrade_advcutter") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) + +/datum/techweb_node/neural_programming + id = "neural_programming" + display_name = "Neural Programming" + description = "Study into networks of processing units that mimic our brains." + prereq_ids = list("biotech", "datatheory") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/posibrain + id = "posibrain" + display_name = "Positronic Brain" + description = "Applied usage of neural technology allowing for autonomous AI units based on special metallic cubes with conductive and processing circuits." + prereq_ids = list("neural_programming") + design_ids = list("mmi_posi") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/cyborg_upg_util + id = "cyborg_upg_util" + display_name = "Cyborg Upgrades: Utility" + description = "Utility upgrades for cyborgs." + prereq_ids = list("engineering", "robotics") + design_ids = list("borg_upgrade_lavaproof", "borg_upgrade_thrusters", "borg_upgrade_selfrepair", "borg_upgrade_expand", "borg_upgrade_rped") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + +/datum/techweb_node/cyborg_upg_med + id = "cyborg_upg_med" + display_name = "Cyborg Upgrades: Medical" + description = "Medical upgrades for cyborgs." + prereq_ids = list("adv_biotech", "robotics") + design_ids = list("borg_upgrade_advhealth", "borg_upgrade_piercinghypospray", "borg_upgrade_highstrengthsynthesiser", "borg_upgrade_expandedsynthesiser", "borg_upgrade_pinpointer", "borg_upgrade_surgicalprocessor") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + +/datum/techweb_node/cyborg_upg_combat + id = "cyborg_upg_combat" + display_name = "Cyborg Upgrades: Combat" + description = "Military grade upgrades for cyborgs." + prereq_ids = list("adv_robotics", "adv_engi" , "weaponry") + design_ids = list("borg_upgrade_vtec", "borg_upgrade_disablercooler") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + +/datum/techweb_node/ai + id = "ai" + display_name = "Artificial Intelligence" + description = "AI unit research." + prereq_ids = list("robotics", "posibrain") + design_ids = list("aifixer", "aicore", "safeguard_module", "onehuman_module", "protectstation_module", "quarantine_module", "oxygen_module", "freeform_module", + "reset_module", "purge_module", "remove_module", "freeformcore_module", "asimov_module", "paladin_module", "tyrant_module", "corporate_module", + "default_module", "borg_ai_control", "mecha_tracking_ai_control", "aiupload", "intellicard") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) diff --git a/code/modules/research/techweb/nodes/syndicate_nodes.dm b/code/modules/research/techweb/nodes/syndicate_nodes.dm new file mode 100644 index 0000000000..193ed8653b --- /dev/null +++ b/code/modules/research/techweb/nodes/syndicate_nodes.dm @@ -0,0 +1,50 @@ + +/datum/techweb_node/syndicate_basic + id = "syndicate_basic" + display_name = "Illegal Technology" + description = "Dangerous research used to create dangerous objects." + prereq_ids = list("adv_engi", "adv_weaponry", "explosive_weapons") + design_ids = list("decloner", "borg_syndicate_module", "suppressor", "largecrossbow", "donksofttoyvendor", "donksoft_refill", "syndiesleeper") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) + hidden = TRUE + +/datum/techweb_node/syndicate_basic/New() //Crappy way of making syndicate gear decon supported until there's another way. + . = ..() + boost_item_paths = list() + for(var/path in GLOB.uplink_items) + var/datum/uplink_item/UI = new path + if(!UI.item || !UI.illegal_tech) + continue + boost_item_paths |= UI.item //allows deconning to unlock. + +/datum/techweb_node/advanced_illegal_ballistics + id = "advanced_illegal_ballistics" + display_name = "Advanced Non-Standard Ballistics" + description = "Ballistic ammunition for non-standard firearms. Usually the ones you don't have nor want to be involved with." + design_ids = list("10mm","10mmap","10mminc","10mmhp","sl357","sl357ap","pistolm9mm","m45","bolt_clip") + prereq_ids = list("ballistic_weapons","syndicate_basic","explosive_weapons") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 25000) //This gives sec lethal mags/clips for guns from traitors, space, or anything in between. + +//Helpers for debugging/balancing the techweb in its entirety! + +/proc/total_techweb_points() + var/list/datum/techweb_node/processing = list() + for(var/i in subtypesof(/datum/techweb_node)) + processing += new i + var/datum/techweb/TW = new + TW.research_points = list() + for(var/i in processing) + var/datum/techweb_node/TN = i + TW.add_point_list(TN.research_costs) + return TW.research_points + +/proc/total_techweb_points_printout() + var/list/datum/techweb_node/processing = list() + for(var/i in subtypesof(/datum/techweb_node)) + processing += new i + var/datum/techweb/TW = new + TW.research_points = list() + for(var/i in processing) + var/datum/techweb_node/TN = i + TW.add_point_list(TN.research_costs) + return TW.printout_points() diff --git a/code/modules/research/techweb/nodes/tools_nodes.dm b/code/modules/research/techweb/nodes/tools_nodes.dm new file mode 100644 index 0000000000..5d8d40f10d --- /dev/null +++ b/code/modules/research/techweb/nodes/tools_nodes.dm @@ -0,0 +1,57 @@ + +////////////////////////Tools//////////////////////// +/datum/techweb_node/basic_tools + id = "basic_tools" + display_name = "Basic Tools" + description = "Basic mechanical, electronic, surgical and botanical tools." + prereq_ids = list("base") + design_ids = list("screwdriver", "wrench", "wirecutters", "crowbar", "multitool", "welding_tool", "tscanner", "analyzer", "cable_coil", "pipe_painter", "airlock_painter", "scalpel", "circular_saw", "surgicaldrill", "retractor", "cautery", "hemostat", "cultivator", "plant_analyzer", "shovel", "spade", "hatchet", "mop", "broom", "normtrash") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 500) + +/datum/techweb_node/basic_mining + id = "basic_mining" + display_name = "Mining Technology" + description = "Better than Efficiency V." + prereq_ids = list("engineering", "basic_plasma") + design_ids = list("drill", "superresonator", "triggermod", "damagemod", "cooldownmod", "rangemod", "ore_redemption", "mining_equipment_vendor", "cargoexpress", "plasmacutter")//e a r l y g a m e) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/adv_mining + id = "adv_mining" + display_name = "Advanced Mining Technology" + description = "Efficiency Level 127" //dumb mc references + prereq_ids = list("basic_mining", "adv_engi", "adv_power", "adv_plasma") + design_ids = list("drill_diamond", "jackhammer", "hypermod", "plasmacutter_adv", "ore_silo", "plasteel_pick", "titanium_pick") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/janitor + id = "janitor" + display_name = "Advanced Sanitation Technology" + description = "Clean things better, faster, stronger, and harder!" + prereq_ids = list("adv_engi") + design_ids = list("advmop", "buffer", "light_replacer", "spraybottle", "beartrap", "ci-janitor", "paint_remover") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1750) // No longer has its bag + +/datum/techweb_node/botany + id = "botany" + display_name = "Botanical Engineering" + description = "Botanical tools." + prereq_ids = list("adv_engi", "biotech") + design_ids = list("diskplantgene", "portaseeder", "plantgenes", "flora_gun", "hydro_tray", "biogenerator", "seed_extractor") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) + +/datum/techweb_node/exp_tools + id = "exp_tools" + display_name = "Experimental Tools" + description = "Highly advanced construction tools." + design_ids = list("exwelder", "jawsoflife", "handdrill", "holosigncombifan") + prereq_ids = list("adv_engi") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) + +/datum/techweb_node/sec_basic + id = "sec_basic" + display_name = "Basic Security Equipment" + description = "Standard equipment used by security." + design_ids = list("seclite", "pepperspray", "bola_energy", "zipties", "evidencebag") + prereq_ids = list("base") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 750) diff --git a/code/modules/research/techweb/nodes/weaponry_nodes.dm b/code/modules/research/techweb/nodes/weaponry_nodes.dm new file mode 100644 index 0000000000..e17d7e1e7b --- /dev/null +++ b/code/modules/research/techweb/nodes/weaponry_nodes.dm @@ -0,0 +1,97 @@ + +/////////////////////////weaponry tech///////////////////////// +/datum/techweb_node/weaponry + id = "weaponry" + display_name = "Weapon Development Technology" + description = "Our researchers have found new to weaponize just about everything now." + prereq_ids = list("engineering") + design_ids = list("pin_testing", "tele_shield", "lasercarbine") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) + +/datum/techweb_node/adv_weaponry + id = "adv_weaponry" + display_name = "Advanced Weapon Development Technology" + description = "Our weapons are breaking the rules of reality by now." + prereq_ids = list("adv_engi", "weaponry") + design_ids = list("pin_loyalty", "laser_shield", "bullet_shield") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) + +/datum/techweb_node/electric_weapons + id = "electronic_weapons" + display_name = "Electric Weapons" + description = "Weapons using electric technology" + prereq_ids = list("weaponry", "adv_power" , "emp_basic") + design_ids = list("stunrevolver", "stunshell", "ioncarbine") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) + +/datum/techweb_node/radioactive_weapons + id = "radioactive_weapons" + display_name = "Radioactive Weaponry" + description = "Weapons using radioactive technology." + prereq_ids = list("adv_engi", "adv_weaponry") + design_ids = list("nuclear_gun") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/magnetic_weapons + id = "magnetic_weapons" + display_name = "Magnetic Weapons" + description = "Weapons using magnetic technology" + prereq_ids = list("weaponry", "adv_weaponry", "emp_adv") + design_ids = list("magrifle", "magpistol", "mag_magrifle", "mag_magrifle_nl", "mag_magpistol", "mag_magpistol_nl") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/medical_weapons + id = "medical_weapons" + display_name = "Medical Weaponry" + description = "Weapons using medical technology." + prereq_ids = list("adv_biotech", "adv_weaponry") + design_ids = list("rapidsyringe", "shotgundartcryostatis") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + +/datum/techweb_node/beam_weapons + id = "beam_weapons" + display_name = "Beam Weaponry" + description = "Various basic beam weapons" + prereq_ids = list("adv_weaponry") + design_ids = list("temp_gun", "xray_laser") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/adv_beam_weapons + id = "adv_beam_weapons" + display_name = "Advanced Beam Weaponry" + description = "Various advanced beam weapons" + prereq_ids = list("beam_weapons") + design_ids = list("beamrifle") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3250) // Sniper + +/datum/techweb_node/explosive_weapons + id = "explosive_weapons" + display_name = "Explosive & Pyrotechnical Weaponry" + description = "If the light stuff just won't do it." + prereq_ids = list("adv_weaponry") + design_ids = list("large_Grenade", "pyro_Grenade", "adv_Grenade") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) + +/datum/techweb_node/ballistic_weapons + id = "ballistic_weapons" + display_name = "Ballistic Weaponry" + description = "This isn't research.. This is reverse-engineering!" + prereq_ids = list("weaponry") + design_ids = list("mag_oldsmg", "mag_oldsmg_ap", "mag_oldsmg_ic", "mag_oldsmg_rubber", "mag_oldsmg_tx") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) + +/datum/techweb_node/exotic_ammo + id = "exotic_ammo" + display_name = "Exotic Ammunition" + description = "They won't know what hit em." + prereq_ids = list("weaponry", "ballistic_weapons") + design_ids = list("techshotshell", "c38_hotshot", "c38_iceblox") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) + +/datum/techweb_node/gravity_gun + id = "gravity_gun" + display_name = "One-point Bluespace-gravitational Manipulator" + description = "Fancy wording for gravity gun." + prereq_ids = list("adv_weaponry", "adv_bluespace") + design_ids = list("gravitygun", "mech_gravcatapult") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index e153176cbe..ed43576a61 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -917,7 +917,7 @@ datum/status_effect/stabilized/blue/on_remove() healing_types += CLONE if(length(healing_types)) owner.apply_damage_type(-heal_amount, damagetype=pick(healing_types)) - owner.nutrition += 3 + owner.adjust_nutrition(3) M.adjustCloneLoss(heal_amount * 1.2) //This way, two people can't just convert each other's damage away. else messagedelivered = FALSE @@ -959,9 +959,10 @@ datum/status_effect/stabilized/blue/on_remove() familiar = new linked.mob_type(get_turf(owner.loc)) familiar.name = linked.mob_name familiar.del_on_death = TRUE - familiar.copy_known_languages_from(owner, FALSE) + familiar.copy_languages(owner, LANGUAGE_MASTER) if(linked.saved_mind) linked.saved_mind.transfer_to(familiar) + familiar.update_atom_languages() familiar.ckey = linked.saved_mind.key else if(familiar.mind) diff --git a/code/modules/research/xenobiology/crossbreeding/burning.dm b/code/modules/research/xenobiology/crossbreeding/burning.dm index 48e6f720b0..7b5004e722 100644 --- a/code/modules/research/xenobiology/crossbreeding/burning.dm +++ b/code/modules/research/xenobiology/crossbreeding/burning.dm @@ -35,7 +35,7 @@ Burning extracts: S.visible_message("A baby slime emerges from [src], and it nuzzles [user] before burbling hungrily!") S.Friends[user] = 20 //Gas, gas, gas S.bodytemperature = T0C + 400 //We gonna step on the gas. - S.nutrition = S.get_hunger_nutrition() //Tonight, we fight! + S.set_nutrition(S.get_hunger_nutrition()) //Tonight, we fight! ..() /obj/item/slimecross/burning/orange diff --git a/code/modules/research/xenobiology/crossbreeding/regenerative.dm b/code/modules/research/xenobiology/crossbreeding/regenerative.dm index b33cee3a64..6b2b0b458c 100644 --- a/code/modules/research/xenobiology/crossbreeding/regenerative.dm +++ b/code/modules/research/xenobiology/crossbreeding/regenerative.dm @@ -128,7 +128,7 @@ Regenerative extracts: colour = "silver" /obj/item/slimecross/regenerative/silver/core_effect(mob/living/target, mob/user) - target.nutrition = NUTRITION_LEVEL_FULL - 1 + target.set_nutrition(NUTRITION_LEVEL_FULL - 1) to_chat(target, "You feel satiated.") /obj/item/slimecross/regenerative/bluespace diff --git a/code/modules/research/xenobiology/crossbreeding/stabilized.dm b/code/modules/research/xenobiology/crossbreeding/stabilized.dm index 1912ca6476..8fbe841828 100644 --- a/code/modules/research/xenobiology/crossbreeding/stabilized.dm +++ b/code/modules/research/xenobiology/crossbreeding/stabilized.dm @@ -158,7 +158,7 @@ Stabilized extracts: /obj/item/slimecross/stabilized/rainbow/attackby(obj/item/O, mob/user) var/obj/item/slimecross/regenerative/regen = O - if(istype(O) && !regencore) + if(istype(regen) && !regencore) to_chat(user, "You place the [O] in the [src], prepping the extract for automatic application!") regencore = regen regen.forceMove(src) diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 573a735f98..bc78e3ab1a 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -186,7 +186,7 @@ /obj/item/slime_extract/purple/activate(mob/living/carbon/human/user, datum/species/jelly/luminescent/species, activation_type) switch(activation_type) if(SLIME_ACTIVATE_MINOR) - user.nutrition += 50 + user.adjust_nutrition(50) user.blood_volume += 50 to_chat(user, "You activate [src], and your body is refilled with fresh slime jelly!") return 150 @@ -636,7 +636,7 @@ qdel(src) return M.docile = 1 - M.nutrition = 700 + M.set_nutrition(700) to_chat(M, "You absorb the potion and feel your intense desire to feed melt away.") to_chat(user, "You feed the slime the potion, removing its hunger and calming it.") var/newname = reject_bad_name(stripped_input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime", MAX_NAME_LEN), TRUE) @@ -684,7 +684,7 @@ if(SM.flags_1 & HOLOGRAM_1) //Check to see if it's a holodeck creature to_chat(SM, "You also become depressingly aware that you are not a real creature, but instead a holoform. Your existence is limited to the parameters of the holodeck.") to_chat(user, "[SM] accepts [src] and suddenly becomes attentive and aware. It worked!") - SM.copy_known_languages_from(user, FALSE) + SM.copy_languages(user) after_success(user, SM) qdel(src) else diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm index 2192b2fddb..45b6939f42 100644 --- a/code/modules/ruins/lavaland_ruin_code.dm +++ b/code/modules/ruins/lavaland_ruin_code.dm @@ -133,7 +133,7 @@ assignedrole = "Lavaland Syndicate" /obj/effect/mob_spawn/human/lavaland_syndicate/special(mob/living/new_spawn) - new_spawn.grant_language(/datum/language/codespeak) + new_spawn.grant_language(/datum/language/codespeak, TRUE, TRUE, LANGUAGE_MIND) /datum/outfit/lavaland_syndicate name = "Lavaland Syndicate Agent" diff --git a/code/modules/ruins/spaceruin_code/clericsden.dm b/code/modules/ruins/spaceruin_code/clericsden.dm index 67e071b274..7d1fda6740 100644 --- a/code/modules/ruins/spaceruin_code/clericsden.dm +++ b/code/modules/ruins/spaceruin_code/clericsden.dm @@ -27,7 +27,8 @@ melee_damage_lower = 8 melee_damage_upper = 10 retreat_distance = 4 //AI proteons will rapidly move in and out of combat to avoid conflict, but will still target and follow you. - attacktext = "pinches" + attack_verb_continuous = "pinches" + attack_verb_simple = "pinch" environment_smash = ENVIRONMENT_SMASH_WALLS attack_sound = 'sound/weapons/punch2.ogg' playstyle_string = "You are a Proteon. Your abilities in combat are outmatched by most combat constructs, but you are still fast and nimble. Run metal and supplies, and cooperate with your fellow cultists." diff --git a/code/modules/ruins/spaceruin_code/listeningstation.dm b/code/modules/ruins/spaceruin_code/listeningstation.dm index 8efeaaabff..e48a1c45d5 100644 --- a/code/modules/ruins/spaceruin_code/listeningstation.dm +++ b/code/modules/ruins/spaceruin_code/listeningstation.dm @@ -32,7 +32,7 @@ /obj/item/paper/fluff/ruins/listeningstation/receipt name = "receipt" - info = "1 x Stechkin pistol - $600
1 x silencer - $200
shipping charge - $4360
total - $5160" + info = "1 x Stechkin pistol - 600 cr
1 x silencer - 200 cr
shipping charge - 4360 cr
total - 5160 cr" /obj/item/paper/fluff/ruins/listeningstation/odd_report name = "odd report" diff --git a/code/modules/security_levels/keycard_authentication.dm b/code/modules/security_levels/keycard_authentication.dm index b9dc9b92d3..04f2de9bec 100644 --- a/code/modules/security_levels/keycard_authentication.dm +++ b/code/modules/security_levels/keycard_authentication.dm @@ -9,6 +9,7 @@ GLOBAL_DATUM_INIT(keycard_events, /datum/events, new) desc = "This device is used to trigger station functions, which require more than one ID card to authenticate." icon = 'icons/obj/monitors.dmi' icon_state = "auth_off" + plane = ABOVE_WALL_PLANE use_power = IDLE_POWER_USE idle_power_usage = 2 active_power_usage = 6 diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm index bdf6e8cc87..a4ef2dfde9 100644 --- a/code/modules/shuttle/supply.dm +++ b/code/modules/shuttle/supply.dm @@ -109,30 +109,46 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list( continue empty_turfs += T + var/datum/bank_account/cargo_budget = SSeconomy.get_dep_account(ACCOUNT_CAR) var/value = 0 var/purchases = 0 for(var/datum/supply_order/SO in SSshuttle.shoppinglist) if(!empty_turfs.len) break - if(SO.pack.cost > SSshuttle.points) - continue - SSshuttle.points -= SO.pack.cost + var/price = SO.pack.cost + var/datum/bank_account/D + if(SO.paying_account) //Someone paid out of pocket + D = SO.paying_account + price *= 1.1 //TODO make this customizable by the quartermaster + else + D = cargo_budget + if(D) + if(!D.adjust_money(-SO.pack.cost)) + if(SO.paying_account) + D.bank_card_talk("Cargo order #[SO.id] rejected due to lack of funds. Credits required: [price]") + continue + + if(SO.paying_account) + D.bank_card_talk("Cargo order #[SO.id] has shipped. [price] credits have been charged to your bank account.") + var/datum/bank_account/department/cargo = SSeconomy.get_dep_account(ACCOUNT_CAR) + cargo.adjust_money(price - SO.pack.cost) //Cargo gets the handling fee value += SO.pack.cost SSshuttle.shoppinglist -= SO SSshuttle.orderhistory += SO SO.generate(pick_n_take(empty_turfs)) SSblackbox.record_feedback("nested tally", "cargo_imports", 1, list("[SO.pack.cost]", "[SO.pack.name]")) - investigate_log("Order #[SO.id] ([SO.pack.name], placed by [key_name(SO.orderer_ckey)]) has shipped.", INVESTIGATE_CARGO) + investigate_log("Order #[SO.id] ([SO.pack.name], placed by [key_name(SO.orderer_ckey)]), paid by [D.account_holder] has shipped.", INVESTIGATE_CARGO) if(SO.pack.dangerous) - message_admins("\A [SO.pack.name] ordered by [ADMIN_LOOKUPFLW(SO.orderer_ckey)] has shipped.") + message_admins("\A [SO.pack.name] ordered by [ADMIN_LOOKUPFLW(SO.orderer_ckey)], paid by [D.account_holder] has shipped.") purchases++ - investigate_log("[purchases] orders in this shipment, worth [value] credits. [SSshuttle.points] credits left.", INVESTIGATE_CARGO) + investigate_log("[purchases] orders in this shipment, worth [value] credits. [cargo_budget.account_balance] credits left.", INVESTIGATE_CARGO) /obj/docking_port/mobile/supply/proc/sell() - var/presale_points = SSshuttle.points + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + var/gain = 0 if(!GLOB.exports_list.len) // No exports list? Generate it! setupExports() @@ -164,14 +180,15 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list( continue msg += export_text + "\n" - SSshuttle.points += ex.total_value[E] + gain += ex.total_value[E] for(var/chem in ex.reagents_value) var/value = ex.reagents_value[chem] msg += "[value > 0 ? "+" : ""][value] credits: received [ex.reagents_volume[chem]]u of [chem].\n" - SSshuttle.points += value + gain += value + D.adjust_money(gain) msg = copytext_char(msg, 1, MAX_MESSAGE_LEN) SSshuttle.centcom_message = msg - investigate_log("Shuttle contents sold for [SSshuttle.points - presale_points] credits. Contents: [ex.exported_atoms || "none."] Message: [SSshuttle.centcom_message || "none."]", INVESTIGATE_CARGO) + investigate_log("Shuttle contents sold for [gain] credits. Contents: [ex.exported_atoms || "none."] Message: [SSshuttle.centcom_message || "none."]", INVESTIGATE_CARGO) diff --git a/code/modules/spells/spell_types/aimed.dm b/code/modules/spells/spell_types/aimed.dm index 1a904b1076..8fab4a221d 100644 --- a/code/modules/spells/spell_types/aimed.dm +++ b/code/modules/spells/spell_types/aimed.dm @@ -101,7 +101,7 @@ base_icon_state = "lightning" sound = 'sound/magic/lightningbolt.ogg' active = FALSE - projectile_var_overrides = list("tesla_range" = 15, "tesla_power" = 20000, "tesla_flags" = TESLA_MOB_DAMAGE) + projectile_var_overrides = list("zap_range" = 15, "zap_power" = 20000, "zap_flags" = ZAP_MOB_DAMAGE) active_msg = "You energize your hand with arcane lightning!" deactive_msg = "You let the energy flow out of your hands back into yourself..." projectile_type = /obj/item/projectile/magic/aoe/lightning diff --git a/code/modules/spells/spell_types/devil_boons.dm b/code/modules/spells/spell_types/devil_boons.dm index ab3e3cc27e..8ba106d77b 100644 --- a/code/modules/spells/spell_types/devil_boons.dm +++ b/code/modules/spells/spell_types/devil_boons.dm @@ -16,14 +16,14 @@ for(var/mob/living/carbon/C in targets) if(user.dropItemToGround(user.get_active_held_item())) var/obj/item = pick( - new /obj/item/coin/gold(user.loc), - new /obj/item/coin/diamond(user.loc), - new /obj/item/coin/silver(user.loc), - new /obj/item/clothing/accessory/medal/gold(user.loc), - new /obj/item/stack/sheet/mineral/gold(user.loc), - new /obj/item/stack/sheet/mineral/silver(user.loc), - new /obj/item/stack/sheet/mineral/diamond(user.loc), - new /obj/item/stack/spacecash/c1000(user.loc)) + new /obj/item/coin/gold(user.drop_location()), + new /obj/item/coin/diamond(user.drop_location()), + new /obj/item/coin/silver(user.drop_location()), + new /obj/item/clothing/accessory/medal/gold(user.drop_location()), + new /obj/item/stack/sheet/mineral/gold(user.drop_location()), + new /obj/item/stack/sheet/mineral/silver(user.drop_location()), + new /obj/item/stack/sheet/mineral/diamond(user.drop_location()), + new /obj/item/holochip(user.drop_location(), 1000)) C.put_in_hands(item) /obj/effect/proc_holder/spell/targeted/view_range diff --git a/code/modules/surgery/advanced/bioware/nerve_grounding.dm b/code/modules/surgery/advanced/bioware/nerve_grounding.dm index 99902ff6d6..eb70a838a4 100644 --- a/code/modules/surgery/advanced/bioware/nerve_grounding.dm +++ b/code/modules/surgery/advanced/bioware/nerve_grounding.dm @@ -32,13 +32,11 @@ name = "Grounded Nerves" desc = "Nerves form a safe path for electricity to traverse, protecting the body from electric shocks." mod_type = BIOWARE_NERVES - var/prev_coeff /datum/bioware/grounded_nerves/on_gain() ..() - prev_coeff = owner.physiology.siemens_coeff - owner.physiology.siemens_coeff = 0 + ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, "grounded_nerves") /datum/bioware/grounded_nerves/on_lose() ..() - owner.physiology.siemens_coeff = prev_coeff + REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, "grounded_nerves") diff --git a/code/modules/surgery/advanced/lobotomy.dm b/code/modules/surgery/advanced/lobotomy.dm index a41e72b76d..2b2d11e54f 100644 --- a/code/modules/surgery/advanced/lobotomy.dm +++ b/code/modules/surgery/advanced/lobotomy.dm @@ -41,7 +41,7 @@ target.cure_all_traumas(TRAUMA_RESILIENCE_LOBOTOMY) if(target.mind && target.mind.has_antag_datum(/datum/antagonist/brainwashed)) target.mind.remove_antag_datum(/datum/antagonist/brainwashed) - switch(rand(1,4))//Now let's see what hopefully-not-important part of the brain we cut off + switch(rand(1,6))//Now let's see what hopefully-not-important part of the brain we cut off if(1) target.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_MAGIC) if(2) diff --git a/code/modules/surgery/advanced/revival.dm b/code/modules/surgery/advanced/revival.dm index e9f8ff4446..cf3a218d80 100644 --- a/code/modules/surgery/advanced/revival.dm +++ b/code/modules/surgery/advanced/revival.dm @@ -36,7 +36,7 @@ return FALSE if(istype(tool, /obj/item/melee/baton)) var/obj/item/melee/baton/B = tool - if(!B.status) + if(!B.turned_on) to_chat(user, "[B] needs to be active!") return FALSE if(istype(tool, /obj/item/gun/energy)) diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index d9e7012214..f654270df7 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -14,7 +14,6 @@ return FALSE if(HAS_TRAIT(C, TRAIT_NODISMEMBER)) return FALSE - var/obj/item/bodypart/affecting = C.get_bodypart(BODY_ZONE_CHEST) affecting.receive_damage(clamp(brute_dam/2 * affecting.body_damage_coeff, 15, 50), clamp(burn_dam/2 * affecting.body_damage_coeff, 0, 50)) //Damage the chest based on limb's existing damage C.visible_message("[C]'s [src.name] has been violently dismembered!") @@ -44,6 +43,10 @@ throw_at(target_turf, throw_range, throw_speed) return TRUE +/obj/item/bodypart/head/dismember() + if(HAS_TRAIT(owner, TRAIT_NODECAP)) + return FALSE + ..() /obj/item/bodypart/chest/dismember() if(!owner) @@ -53,6 +56,8 @@ return FALSE if(HAS_TRAIT(C, TRAIT_NODISMEMBER)) return FALSE + if(HAS_TRAIT(C, TRAIT_NOGUT)) //Just for not allowing gutting + return FALSE . = list() var/organ_spilled = 0 var/turf/T = get_turf(C) diff --git a/code/modules/surgery/bodyparts/robot_bodyparts.dm b/code/modules/surgery/bodyparts/robot_bodyparts.dm index a3f8b883b4..39e660203e 100644 --- a/code/modules/surgery/bodyparts/robot_bodyparts.dm +++ b/code/modules/surgery/bodyparts/robot_bodyparts.dm @@ -19,7 +19,7 @@ flags_1 = CONDUCT_1 icon_state = "borg_l_arm" status = BODYPART_ROBOTIC - + brute_reduction = 2 burn_reduction = 1 @@ -40,7 +40,7 @@ flags_1 = CONDUCT_1 icon_state = "borg_r_arm" status = BODYPART_ROBOTIC - + brute_reduction = 2 burn_reduction = 1 @@ -61,7 +61,7 @@ flags_1 = CONDUCT_1 icon_state = "borg_l_leg" status = BODYPART_ROBOTIC - + brute_reduction = 2 burn_reduction = 1 @@ -82,7 +82,7 @@ flags_1 = CONDUCT_1 icon_state = "borg_r_leg" status = BODYPART_ROBOTIC - + brute_reduction = 2 burn_reduction = 1 @@ -102,7 +102,7 @@ flags_1 = CONDUCT_1 icon_state = "borg_chest" status = BODYPART_ROBOTIC - + brute_reduction = 2 burn_reduction = 1 @@ -131,8 +131,7 @@ if(src.wired) to_chat(user, "You have already inserted wire!") return - var/obj/item/stack/cable_coil/coil = W - if (coil.use(1)) + if (W.use_tool(src, user, 0, 1)) src.wired = 1 to_chat(user, "You insert the wire.") else @@ -164,7 +163,7 @@ flags_1 = CONDUCT_1 icon_state = "borg_head" status = BODYPART_ROBOTIC - + brute_reduction = 5 burn_reduction = 4 diff --git a/code/modules/surgery/lipoplasty.dm b/code/modules/surgery/lipoplasty.dm index 63e828d3c9..5a0fd819f1 100644 --- a/code/modules/surgery/lipoplasty.dm +++ b/code/modules/surgery/lipoplasty.dm @@ -40,7 +40,7 @@ "[user] extracts [target]'s fat!") target.overeatduration = 0 //patient is unfatted var/removednutriment = target.nutrition - target.nutrition = NUTRITION_LEVEL_WELL_FED + target.set_nutrition(NUTRITION_LEVEL_WELL_FED) removednutriment -= 450 //whatever was removed goes into the meat var/mob/living/carbon/human/H = target var/typeofmeat = /obj/item/reagent_containers/food/snacks/meat/slab/human diff --git a/code/modules/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/augments_chest.dm index 46092ff0c2..fcc3f71b8b 100644 --- a/code/modules/surgery/organs/augments_chest.dm +++ b/code/modules/surgery/organs/augments_chest.dm @@ -23,7 +23,7 @@ if(owner.nutrition <= hunger_threshold) synthesizing = TRUE to_chat(owner, "You feel less hungry...") - owner.nutrition += 50 + owner.adjust_nutrition(50) addtimer(CALLBACK(src, .proc/synth_cool), 50) /obj/item/organ/cyberimp/chest/nutriment/proc/synth_cool() diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm index 1fee605b12..465c10c4cd 100644 --- a/code/modules/surgery/organs/heart.dm +++ b/code/modules/surgery/organs/heart.dm @@ -221,7 +221,7 @@ obj/item/organ/heart/cybernetic/upgraded/on_life() used_dose() if(ramount < 10) //eats your nutrition to regen epinephrine var/regen_amount = owner.nutrition/2000 - owner.nutrition -= regen_amount + owner.adjust_nutrition(-regen_amount) ramount += regen_amount /obj/item/organ/heart/cybernetic/upgraded/proc/used_dose() diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index bcc764d00a..f8547dda6e 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -64,8 +64,8 @@ owner.RegisterSignal(owner, COMSIG_MOB_SAY, /mob/living/carbon/.proc/handle_tongueless_speech) return ..() -/obj/item/organ/tongue/could_speak_in_language(datum/language/dt) - return is_type_in_typecache(dt, languages_possible) +/obj/item/organ/tongue/could_speak_language(language) + return is_type_in_typecache(language, languages_possible) /obj/item/organ/tongue/lizard name = "forked tongue" @@ -141,7 +141,7 @@ /obj/item/organ/tongue/abductor/handle_speech(datum/source, list/speech_args) //Hacks var/message = speech_args[SPEECH_MESSAGE] - var/mob/living/carbon/human/user = usr + var/mob/living/carbon/human/user = source var/rendered = "[user.name]: [message]" user.log_talk(message, LOG_SAY, tag="abductor") for(var/mob/living/carbon/human/H in GLOB.alive_mob_list) @@ -260,7 +260,7 @@ maxHealth = 100 //RoboTongue! var/electronics_magic = TRUE -/obj/item/organ/tongue/robot/can_speak_in_language(datum/language/dt) +/obj/item/organ/tongue/robot/could_speak_language(language) return ..() || electronics_magic /obj/item/organ/tongue/robot/handle_speech(datum/source, list/speech_args) diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index 671d31530a..65e53df26f 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -1254,12 +1254,12 @@ if (trigger2 == "speak" || trigger2 == "echo") var/trigger3 = html_decode(stripped_input(user, "Enter the phrase spoken. Abusing this to self antag is bannable.", MAX_MESSAGE_LEN)) E.customTriggers[trigger] = list(trigger2, trigger3) - log_game("FERMICHEM: [H] has been implanted by [user] with [trigger], triggering [trigger2], to send [trigger3].") + log_reagent("FERMICHEM: [H] has been implanted by [user] with [trigger], triggering [trigger2], to send [trigger3].") if(findtext(trigger3, "admin")) message_admins("FERMICHEM: [user] maybe be trying to abuse MKUltra by implanting by [H] with [trigger], triggering [trigger2], to send [trigger3].") else E.customTriggers[trigger] = trigger2 - log_game("FERMICHEM: [H] has been implanted by [user] with [trigger], triggering [trigger2].") + log_reagent("FERMICHEM: [H] has been implanted by [user] with [trigger], triggering [trigger2].") E.mental_capacity -= 5 addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "[(E.lewd?"your [E.enthrallGender]":"[E.master]")] whispers you a new trigger."), 5) to_chat(user, "You sucessfully set the trigger word [trigger] in [H]") @@ -1322,7 +1322,7 @@ objective = replacetext(lowertext(objective), "strangle", "meow at") objective = replacetext(lowertext(objective), "suicide", "self-love") message_admins("[H] has been implanted by [user] with the objective [objective].") - log_game("FERMICHEM: [H] has been implanted by [user] with the objective [objective] via MKUltra.") + log_reagent("FERMICHEM: [H] has been implanted by [user] with the objective [objective] via MKUltra.") addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "[(E.lewd?"Your [E.enthrallGender]":"[E.master]")] whispers you a new objective."), 5) brainwash(H, objective) E.mental_capacity -= 200 @@ -1341,7 +1341,7 @@ var/instill = stripped_input(user, "Instill an emotion in [H].", MAX_MESSAGE_LEN) to_chat(H, "[instill]") to_chat(user, "You sucessfully instill a feeling in [H]") - log_game("FERMICHEM: [H] has been instilled by [user] with [instill] via MKUltra.") + log_reagent("FERMICHEM: [H] has been instilled by [user] with [instill] via MKUltra.") E.cooldown += 1 //RECOGNISE @@ -1455,7 +1455,7 @@ if(message_admins || debug)//Do you want this in? message_admins("[ADMIN_LOOKUPFLW(user)] has said '[log_message]' with a Velvet Voice, affecting [english_list(listeners)], with a power multiplier of [power_multiplier].") - log_game("FERMICHEM: [key_name(user)] ckey: [user.key] has said '[log_message]' with a Velvet Voice, affecting [english_list(listeners)], with a power multiplier of [power_multiplier].") + log_reagent("FERMICHEM: [key_name(user)] ckey: [user.key] has said '[log_message]' with a Velvet Voice, affecting [english_list(listeners)], with a power multiplier of [power_multiplier].") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times people have spoken with a velvet voice") //SSblackbox.record_feedback("tally", "Velvet_voice", 1, log_message) If this is on, it fills the thing up and OOFs the server diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index 7127b41ee3..e287b38ca1 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -57,11 +57,11 @@ surgery.step_in_progress = FALSE return FALSE if(tool) - speed_mod = tool.toolspeed - var/skill_mod = 1 - if(user?.mind?.skill_holder) - skill_mod = SURGERY_SKILL_SPEEDUP_NUMERICAL_SCALE(user.mind.skill_holder.get_skill_value(/datum/skill/numerical/surgery)) - if(do_after(user, time * speed_mod * skill_mod, target = target)) + speed_mod = tool.toolspeed //faster tools mean faster surgeries, but also less experience. + if(user.mind) + speed_mod = user.mind.action_skill_mod(/datum/skill/numerical/surgery, speed_mod, THRESHOLD_UNTRAINED, FALSE) + var/delay = time * speed_mod + if(do_after(user, delay, target = target)) var/prob_chance = 100 if(implement_type) //this means it isn't a require hand or any item step. prob_chance = implements[implement_type] @@ -69,7 +69,10 @@ if((prob(prob_chance) || (iscyborg(user) && !silicons_obey_prob)) && chem_check(target) && !try_to_fail) if(success(user, target, target_zone, tool, surgery)) - user?.mind?.skill_holder?.auto_gain_experience(/datum/skill/numerical/surgery, SKILL_GAIN_SURGERY_PER_STEP) + var/multi = (delay/SKILL_GAIN_DELAY_DIVISOR) + if(repeatable) + multi *= 0.5 //Spammable surgeries award less experience. + user.mind?.auto_gain_experience(/datum/skill/numerical/surgery, SKILL_GAIN_SURGERY_PER_STEP * multi) advance = TRUE else if(failure(user, target, target_zone, tool, surgery)) diff --git a/code/modules/tgs/core/core.dm b/code/modules/tgs/core/core.dm index 70252cfb49..a74c9bbab2 100644 --- a/code/modules/tgs/core/core.dm +++ b/code/modules/tgs/core/core.dm @@ -1,11 +1,17 @@ /world/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE) var/current_api = TGS_READ_GLOBAL(tgs) if(current_api) - TGS_ERROR_LOG("TgsNew(): TGS API datum already set ([current_api])! Was TgsNew() called more than once?") + TGS_ERROR_LOG("API datum already set (\ref[current_api] ([current_api]))! Was TgsNew() called more than once?") + return + + if(!(minimum_required_security_level in list(TGS_SECURITY_ULTRASAFE, TGS_SECURITY_SAFE, TGS_SECURITY_TRUSTED))) + TGS_ERROR_LOG("Invalid minimum_required_security_level: [minimum_required_security_level]!") return #ifdef TGS_V3_API - minimum_required_security_level = TGS_SECURITY_TRUSTED + if(minimum_required_security_level != TGS_SECURITY_TRUSTED) + TGS_WARNING_LOG("V3 DMAPI requires trusted security!") + minimum_required_security_level = TGS_SECURITY_TRUSTED #endif var/raw_parameter = world.params[TGS_VERSION_PARAMETER] if(!raw_parameter) @@ -13,7 +19,7 @@ var/datum/tgs_version/version = new(raw_parameter) if(!version.Valid(FALSE)) - TGS_ERROR_LOG("Failed to validate TGS version parameter: [raw_parameter]!") + TGS_ERROR_LOG("Failed to validate DMAPI version parameter: [raw_parameter]!") return var/api_datum @@ -21,18 +27,21 @@ if(3) #ifndef TGS_V3_API TGS_ERROR_LOG("Detected V3 API but TGS_V3_API isn't defined!") + return #else - switch(version.major) + switch(version.minor) if(2) api_datum = /datum/tgs_api/v3210 #endif if(4) - switch(version.major) + switch(version.minor) if(0) api_datum = /datum/tgs_api/v4 + if(5) + api_datum = /datum/tgs_api/v5 var/datum/tgs_version/max_api_version = TgsMaximumAPIVersion(); - if(version.suite != null && version.major != null && version.minor != null && version.patch != null && version.deprefixed_parameter > max_api_version.deprefixed_parameter) + if(version.suite != null && version.minor != null && version.patch != null && version.deprecated_patch != null && version.deprefixed_parameter > max_api_version.deprefixed_parameter) TGS_ERROR_LOG("Detected unknown API version! Defaulting to latest. Update the DMAPI to fix this problem.") api_datum = /datum/tgs_api/latest @@ -41,20 +50,25 @@ return TGS_INFO_LOG("Activating API for version [version.deprefixed_parameter]") - var/datum/tgs_api/new_api = new api_datum(version) + + if(event_handler && !istype(event_handler)) + TGS_ERROR_LOG("Invalid parameter for event_handler: [event_handler]") + event_handler = null + + var/datum/tgs_api/new_api = new api_datum(event_handler, version) TGS_WRITE_GLOBAL(tgs, new_api) - var/result = new_api.OnWorldNew(event_handler, minimum_required_security_level) + var/result = new_api.OnWorldNew(minimum_required_security_level) if(!result || result == TGS_UNIMPLEMENTED) TGS_WRITE_GLOBAL(tgs, null) TGS_ERROR_LOG("Failed to activate API!") /world/TgsMaximumAPIVersion() - return new /datum/tgs_version("4.0.x.x") + return new /datum/tgs_version("5.x.x") /world/TgsMinimumAPIVersion() - return new /datum/tgs_version("3.2.0.0") + return new /datum/tgs_version("3.2.x") /world/TgsInitializationComplete() var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) @@ -88,6 +102,11 @@ if(api) return api.version +/world/TgsApiVersion() + var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) + if(api) + return api.ApiVersion() + /world/TgsInstanceName() var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) if(api) diff --git a/code/modules/tgs/core/datum.dm b/code/modules/tgs/core/datum.dm index fb2508059a..ccc75fe344 100644 --- a/code/modules/tgs/core/datum.dm +++ b/code/modules/tgs/core/datum.dm @@ -2,13 +2,15 @@ TGS_DEFINE_AND_SET_GLOBAL(tgs, null) /datum/tgs_api var/datum/tgs_version/version + var/datum/tgs_event_handler/event_handler -/datum/tgs_api/New(datum/tgs_version/version) +/datum/tgs_api/New(datum/tgs_event_handler/event_handler, datum/tgs_version/version) . = ..() + src.event_handler = event_handler src.version = version /datum/tgs_api/latest - parent_type = /datum/tgs_api/v4 + parent_type = /datum/tgs_api/v5 TGS_PROTECT_DATUM(/datum/tgs_api) diff --git a/code/modules/tgs/core/tgs_version.dm b/code/modules/tgs/core/tgs_version.dm index b97745611f..a5dae1241a 100644 --- a/code/modules/tgs/core/tgs_version.dm +++ b/code/modules/tgs/core/tgs_version.dm @@ -5,11 +5,11 @@ suite = text2num(version_bits[1]) if(version_bits.len > 1) - major = text2num(version_bits[2]) + minor = text2num(version_bits[2]) if(version_bits.len > 2) - minor = text2num(version_bits[3]) + patch = text2num(version_bits[3]) if(version_bits.len == 4) - patch = text2num(version_bits[4]) + deprecated_patch = text2num(version_bits[4]) /datum/tgs_version/proc/Valid(allow_wildcards = FALSE) if(suite == null) @@ -19,4 +19,10 @@ return !Wildcard() /datum/tgs_version/Wildcard() - return major == null || minor == null || patch == null + return minor == null || patch == null + +/datum/tgs_version/Equals(datum/tgs_version/other_version) + if(!istype(other_version)) + return FALSE + + return suite == other_version.suite && minor == other_version.minor && patch == other_version.patch && deprecated_patch == other_version.deprecated_patch diff --git a/code/modules/tgs/includes.dm b/code/modules/tgs/includes.dm index 247f1fda5d..b3c1728f34 100644 --- a/code/modules/tgs/includes.dm +++ b/code/modules/tgs/includes.dm @@ -2,9 +2,43 @@ #include "core\core.dm" #include "core\datum.dm" #include "core\tgs_version.dm" + #ifdef TGS_V3_API #include "v3210\api.dm" #include "v3210\commands.dm" #endif + #include "v4\api.dm" #include "v4\commands.dm" + +#include "v5\_defines.dm" +#include "v5\api.dm" +#include "v5\commands.dm" +#include "v5\undef.dm" + +/* +The MIT License + +Copyright (c) 2017 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgs/v3210/api.dm b/code/modules/tgs/v3210/api.dm index c536995b04..0fc0076c8b 100644 --- a/code/modules/tgs/v3210/api.dm +++ b/code/modules/tgs/v3210/api.dm @@ -39,7 +39,7 @@ var/warned_custom_commands = FALSE /datum/tgs_api/v3210/ApiVersion() - return "3.2.1.0" + return new /datum/tgs_version("3.2.1.0") /datum/tgs_api/v3210/proc/trim_left(text) for (var/i = 1 to length(text)) @@ -56,7 +56,7 @@ /datum/tgs_api/v3210/proc/file2list(filename) return splittext(trim_left(trim_right(file2text(filename))), "\n") -/datum/tgs_api/v3210/OnWorldNew(datum/tgs_event_handler/event_handler, minimum_required_security_level) //don't use event handling in this version +/datum/tgs_api/v3210/OnWorldNew(minimum_required_security_level) . = FALSE comms_key = world.params[SERVICE_WORLD_PARAM] @@ -76,7 +76,8 @@ TGS_ERROR_LOG("This API version is only supported on Windows. Not running on Windows. Aborting initialization!") return ListServiceCustomCommands(TRUE) - ExportService("[SERVICE_REQUEST_API_VERSION] [ApiVersion()]", TRUE) + var/datum/tgs_version/api_version = ApiVersion() + ExportService("[SERVICE_REQUEST_API_VERSION] [api_version.deprefixed_parameter]", TRUE) return TRUE //nothing to do for v3 @@ -166,7 +167,8 @@ /datum/tgs_api/v3210/Revision() if(!warned_revison) - TGS_ERROR_LOG("Use of TgsRevision on [ApiVersion()] origin_commit only points to master!") + var/datum/tgs_version/api_version = ApiVersion() + TGS_ERROR_LOG("Use of TgsRevision on [api_version.deprefixed_parameter] origin_commit only points to master!") warned_revison = TRUE var/datum/tgs_revision_information/ri = new ri.commit = commit diff --git a/code/modules/tgs/v3210/commands.dm b/code/modules/tgs/v3210/commands.dm index e5bc6f4895..5046631981 100644 --- a/code/modules/tgs/v3210/commands.dm +++ b/code/modules/tgs/v3210/commands.dm @@ -19,7 +19,7 @@ TGS_ERROR_LOG("Custom command [command_name] can't be used as it is empty or contains illegal characters!") warned_command_names[command_name] = TRUE continue - + if(command_name_types[command_name]) if(warnings_only) TGS_ERROR_LOG("Custom commands [command_name_types[command_name]] and [stc] have the same name, only [command_name_types[command_name]] will be available!") @@ -55,24 +55,24 @@ The MIT License Copyright (c) 2017 Jordan Brown -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ diff --git a/code/modules/tgs/v4/api.dm b/code/modules/tgs/v4/api.dm index b61cddbeba..ba18aab688 100644 --- a/code/modules/tgs/v4/api.dm +++ b/code/modules/tgs/v4/api.dm @@ -43,15 +43,13 @@ var/list/cached_test_merges var/datum/tgs_revision_information/cached_revision - var/datum/tgs_event_handler/event_handler - var/export_lock = FALSE var/list/last_interop_response /datum/tgs_api/v4/ApiVersion() - return "4.0.0.0" + return new /datum/tgs_version("4.0.0.0") -/datum/tgs_api/v4/OnWorldNew(datum/tgs_event_handler/event_handler, minimum_required_security_level) +/datum/tgs_api/v4/OnWorldNew(minimum_required_security_level) json_path = world.params[TGS4_PARAM_INFO_JSON] if(!json_path) TGS_ERROR_LOG("Missing [TGS4_PARAM_INFO_JSON] world parameter!") @@ -76,7 +74,6 @@ security_level = cached_json["securityLevel"] chat_channels_json_path = cached_json["chatChannelsJson"] chat_commands_json_path = cached_json["chatCommandsJson"] - src.event_handler = event_handler instance_name = cached_json["instanceName"] ListCustomCommands() diff --git a/code/modules/tgs/v4/commands.dm b/code/modules/tgs/v4/commands.dm index af21a86fb6..1d9951bc04 100644 --- a/code/modules/tgs/v4/commands.dm +++ b/code/modules/tgs/v4/commands.dm @@ -46,24 +46,24 @@ The MIT License Copyright (c) 2017 Jordan Brown -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ diff --git a/code/modules/tgs/v5/_defines.dm b/code/modules/tgs/v5/_defines.dm new file mode 100644 index 0000000000..2baf3e12d7 --- /dev/null +++ b/code/modules/tgs/v5/_defines.dm @@ -0,0 +1,124 @@ +#define DMAPI5_PARAM_SERVER_PORT "tgs_port" +#define DMAPI5_PARAM_ACCESS_IDENTIFIER "tgs_key" + +#define DMAPI5_BRIDGE_DATA "data" +#define DMAPI5_TOPIC_DATA "tgs_data" + +#define DMAPI5_BRIDGE_COMMAND_PORT_UPDATE 0 +#define DMAPI5_BRIDGE_COMMAND_STARTUP 1 +#define DMAPI5_BRIDGE_COMMAND_PRIME 2 +#define DMAPI5_BRIDGE_COMMAND_REBOOT 3 +#define DMAPI5_BRIDGE_COMMAND_KILL 4 +#define DMAPI5_BRIDGE_COMMAND_CHAT_SEND 5 + +#define DMAPI5_PARAMETER_ACCESS_IDENTIFIER "accessIdentifier" +#define DMAPI5_RESPONSE_ERROR_MESSAGE "errorMessage" + +#define DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE "commandType" +#define DMAPI5_BRIDGE_PARAMETER_CURRENT_PORT "currentPort" +#define DMAPI5_BRIDGE_PARAMETER_VERSION "version" +#define DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE "chatMessage" +#define DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS "customCommands" +#define DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL "minimumSecurityLevel" + +#define DMAPI5_BRIDGE_RESPONSE_NEW_PORT "newPort" +#define DMAPI5_BRIDGE_RESPONSE_RUNTIME_INFORMATION "runtimeInformation" + +#define DMAPI5_CHAT_MESSAGE_TEXT "text" +#define DMAPI5_CHAT_MESSAGE_CHANNEL_IDS "channelIds" + +#define DMAPI5_RUNTIME_INFORMATION_ACCESS_IDENTIFIER "accessIdentifier" +#define DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION "serverVersion" +#define DMAPI5_RUNTIME_INFORMATION_SERVER_PORT "serverPort" +#define DMAPI5_RUNTIME_INFORMATION_API_VALIDATE_ONLY "apiValidateOnly" +#define DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME "instanceName" +#define DMAPI5_RUNTIME_INFORMATION_REVISION "revision" +#define DMAPI5_RUNTIME_INFORMATION_TEST_MERGES "testMerges" +#define DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL "securityLevel" + +#define DMAPI5_CHAT_UPDATE_CHANNELS "channels" + +#define DMAPI5_TEST_MERGE_TIME_MERGED "timeMerged" +#define DMAPI5_TEST_MERGE_REVISION "revision" +#define DMAPI5_TEST_MERGE_TITLE_AT_MERGE "titleAtMerge" +#define DMAPI5_TEST_MERGE_BODY_AT_MERGE "bodyAtMerge" +#define DMAPI5_TEST_MERGE_URL "url" +#define DMAPI5_TEST_MERGE_AUTHOR "author" +#define DMAPI5_TEST_MERGE_NUMBER "number" +#define DMAPI5_TEST_MERGE_PULL_REQUEST_REVISION "pullRequestRevision" +#define DMAPI5_TEST_MERGE_COMMENT "comment" + +#define DMAPI5_CHAT_COMMAND_NAME "name" +#define DMAPI5_CHAT_COMMAND_PARAMS "params" +#define DMAPI5_CHAT_COMMAND_USER "user" + +#define DMAPI5_EVENT_NOTIFICATION_TYPE "type" +#define DMAPI5_EVENT_NOTIFICATION_PARAMETERS "parameters" + +#define DMAPI5_TOPIC_COMMAND_CHAT_COMMAND 0 +#define DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION 1 +#define DMAPI5_TOPIC_COMMAND_CHANGE_PORT 2 +#define DMAPI5_TOPIC_COMMAND_CHANGE_REBOOT_STATE 3 +#define DMAPI5_TOPIC_COMMAND_INSTANCE_RENAMED 4 +#define DMAPI5_TOPIC_COMMAND_CHAT_CHANNELS_UPDATE 5 +#define DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE 6 +#define DMAPI5_TOPIC_COMMAND_HEARTBEAT 7 +#define DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH 8 + +#define DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE "commandType" +#define DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND "chatCommand" +#define DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION "eventNotification" +#define DMAPI5_TOPIC_PARAMETER_NEW_PORT "newPort" +#define DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE "newRebootState" +#define DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME "newInstanceName" +#define DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE "chatUpdate" +#define DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION "newServerVersion" + +#define DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE "commandResponseMessage" +#define DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES "chatResponses" + +#define DMAPI5_REVISION_INFORMATION_COMMIT_SHA "commitSha" +#define DMAPI5_REVISION_INFORMATION_ORIGIN_COMMIT_SHA "originCommitSha" + +#define DMAPI5_CHAT_USER_ID "id" +#define DMAPI5_CHAT_USER_FRIENDLY_NAME "friendlyName" +#define DMAPI5_CHAT_USER_MENTION "mention" +#define DMAPI5_CHAT_USER_CHANNEL "channel" + +#define DMAPI5_CHAT_CHANNEL_ID "id" +#define DMAPI5_CHAT_CHANNEL_FRIENDLY_NAME "friendlyName" +#define DMAPI5_CHAT_CHANNEL_CONNECTION_NAME "connectionName" +#define DMAPI5_CHAT_CHANNEL_IS_ADMIN_CHANNEL "isAdminChannel" +#define DMAPI5_CHAT_CHANNEL_IS_PRIVATE_CHANNEL "isPrivateChannel" +#define DMAPI5_CHAT_CHANNEL_TAG "tag" + +#define DMAPI5_CUSTOM_CHAT_COMMAND_NAME "name" +#define DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT "helpText" +#define DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY "adminOnly" + +/* +The MIT License + +Copyright (c) 2020 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgs/v5/api.dm b/code/modules/tgs/v5/api.dm new file mode 100644 index 0000000000..eedefb2877 --- /dev/null +++ b/code/modules/tgs/v5/api.dm @@ -0,0 +1,372 @@ +/datum/tgs_api/v5 + var/server_port + var/access_identifier + + var/instance_name + var/security_level + + var/reboot_mode = TGS_REBOOT_MODE_NORMAL + + var/list/intercepted_message_queue + + var/list/custom_commands + + var/list/test_merges + var/datum/tgs_revision_information/revision + var/list/chat_channels + +/datum/tgs_api/v5/ApiVersion() + return new /datum/tgs_version("5.1.1") + +/datum/tgs_api/v5/OnWorldNew(minimum_required_security_level) + server_port = world.params[DMAPI5_PARAM_SERVER_PORT] + access_identifier = world.params[DMAPI5_PARAM_ACCESS_IDENTIFIER] + + var/datum/tgs_version/api_version = ApiVersion() + version = null + var/list/bridge_response = Bridge(DMAPI5_BRIDGE_COMMAND_STARTUP, list(DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL = minimum_required_security_level, DMAPI5_BRIDGE_PARAMETER_VERSION = api_version.raw_parameter, DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands())) + if(!istype(bridge_response)) + TGS_ERROR_LOG("Failed initial bridge request!") + return FALSE + + var/list/runtime_information = bridge_response[DMAPI5_BRIDGE_RESPONSE_RUNTIME_INFORMATION] + if(!istype(runtime_information)) + TGS_ERROR_LOG("Failed to decode runtime information from bridge response: [json_encode(bridge_response)]!") + return FALSE + + if(runtime_information[DMAPI5_RUNTIME_INFORMATION_API_VALIDATE_ONLY]) + TGS_INFO_LOG("DMAPI validation, exiting...") + del(world) + + version = new /datum/tgs_version(runtime_information[DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION]) + security_level = runtime_information[DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL] + instance_name = runtime_information[DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME] + + var/list/revisionData = runtime_information[DMAPI5_RUNTIME_INFORMATION_REVISION] + if(istype(revisionData)) + revision = new + revision.commit = revisionData[DMAPI5_REVISION_INFORMATION_COMMIT_SHA] + revision.origin_commit = revisionData[DMAPI5_REVISION_INFORMATION_ORIGIN_COMMIT_SHA] + else + TGS_ERROR_LOG("Failed to decode [DMAPI5_RUNTIME_INFORMATION_REVISION] from runtime information!") + + test_merges = list() + var/list/test_merge_json = runtime_information[DMAPI5_RUNTIME_INFORMATION_TEST_MERGES] + if(istype(test_merge_json)) + for(var/entry in test_merge_json) + var/datum/tgs_revision_information/test_merge/tm = new + tm.number = entry[DMAPI5_TEST_MERGE_NUMBER] + + var/list/revInfo = entry[DMAPI5_TEST_MERGE_REVISION] + if(revInfo) + tm.commit = revisionData[DMAPI5_REVISION_INFORMATION_COMMIT_SHA] + tm.origin_commit = revisionData[DMAPI5_REVISION_INFORMATION_ORIGIN_COMMIT_SHA] + else + TGS_WARNING_LOG("Failed to decode [DMAPI5_TEST_MERGE_REVISION] from test merge #[tm.number]!") + + tm.time_merged = text2num(entry[DMAPI5_TEST_MERGE_TIME_MERGED]) + tm.title = entry[DMAPI5_TEST_MERGE_TITLE_AT_MERGE] + tm.body = entry[DMAPI5_TEST_MERGE_BODY_AT_MERGE] + tm.url = entry[DMAPI5_TEST_MERGE_URL] + tm.author = entry[DMAPI5_TEST_MERGE_AUTHOR] + tm.pull_request_commit = entry[DMAPI5_TEST_MERGE_PULL_REQUEST_REVISION] + tm.comment = entry[DMAPI5_TEST_MERGE_COMMENT] + + test_merges += tm + else + TGS_WARNING_LOG("Failed to decode [DMAPI5_RUNTIME_INFORMATION_TEST_MERGES] from runtime information!") + + chat_channels = list() + DecodeChannels(runtime_information) + + return TRUE + +/datum/tgs_api/v5/proc/RequireInitialBridgeResponse() + while(!version) + sleep(1) + +/datum/tgs_api/v5/OnInitializationComplete() + Bridge(DMAPI5_BRIDGE_COMMAND_PRIME) + + var/tgs4_secret_sleep_offline_sauce = 29051994 + var/old_sleep_offline = world.sleep_offline + world.sleep_offline = tgs4_secret_sleep_offline_sauce + sleep(1) + if(world.sleep_offline == tgs4_secret_sleep_offline_sauce) //if not someone changed it + world.sleep_offline = old_sleep_offline + +/datum/tgs_api/v5/proc/TopicResponse(error_message = null) + var/list/response = list() + response[DMAPI5_RESPONSE_ERROR_MESSAGE] = error_message + + return json_encode(response) + +/datum/tgs_api/v5/OnTopic(T) + var/list/params = params2list(T) + var/json = params[DMAPI5_TOPIC_DATA] + if(!json) + return FALSE //continue world/Topic + + var/list/topic_parameters = json_decode(json) + if(!topic_parameters) + return TopicResponse("Invalid topic parameters json!"); + + var/their_sCK = topic_parameters[DMAPI5_PARAMETER_ACCESS_IDENTIFIER] + if(their_sCK != access_identifier) + return TopicResponse("Failed to decode [DMAPI5_PARAMETER_ACCESS_IDENTIFIER] from: [json]!"); + + var/command = topic_parameters[DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE] + if(!isnum(command)) + return TopicResponse("Failed to decode [DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE] from: [json]!") + + switch(command) + if(DMAPI5_TOPIC_COMMAND_CHAT_COMMAND) + var/result = HandleCustomCommand(topic_parameters[DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND]) + if(!result) + result = TopicResponse("Error running chat command!") + return result + if(DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION) + intercepted_message_queue = list() + var/list/event_notification = topic_parameters[DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION] + if(!istype(event_notification)) + return TopicResponse("Invalid [DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION]!") + + var/event_type = event_notification[DMAPI5_EVENT_NOTIFICATION_TYPE] + if(!isnum(event_type)) + return TopicResponse("Invalid or missing [DMAPI5_EVENT_NOTIFICATION_TYPE]!") + + var/list/event_parameters = event_notification[DMAPI5_EVENT_NOTIFICATION_PARAMETERS] + if(event_parameters && !istype(event_parameters)) + return TopicResponse("Invalid or missing [DMAPI5_EVENT_NOTIFICATION_PARAMETERS]!") + + var/list/event_call = list(event_type) + if(event_parameters) + event_call += event_parameters + + if(event_handler != null) + event_handler.HandleEvent(arglist(event_call)) + + var/list/response = list() + response[DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES] = intercepted_message_queue + intercepted_message_queue = null + return json_encode(response) + if(DMAPI5_TOPIC_COMMAND_CHANGE_PORT) + var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT] + if (!isnum(new_port) || !(new_port > 0)) + return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]") + + if(event_handler != null) + event_handler.HandleEvent(TGS_EVENT_PORT_SWAP, new_port) + + //the topic still completes, miraculously + //I honestly didn't believe byond could do it without exploding + if(!world.OpenPort(new_port)) + return TopicResponse("Port change failed!") + + return TopicResponse() + if(DMAPI5_TOPIC_COMMAND_CHANGE_REBOOT_STATE) + var/new_reboot_mode = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE] + if(!isnum(new_reboot_mode)) + return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE]!") + + if(event_handler != null) + event_handler.HandleEvent(TGS_EVENT_REBOOT_MODE_CHANGE, reboot_mode, new_reboot_mode) + + reboot_mode = new_reboot_mode + return TopicResponse() + if(DMAPI5_TOPIC_COMMAND_INSTANCE_RENAMED) + var/new_instance_name = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME] + if(!istext(new_instance_name)) + return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME]!") + + if(event_handler != null) + event_handler.HandleEvent(TGS_EVENT_INSTANCE_RENAMED, new_instance_name) + + instance_name = new_instance_name + return TopicResponse() + if(DMAPI5_TOPIC_COMMAND_CHAT_CHANNELS_UPDATE) + var/list/chat_update_json = topic_parameters[DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE] + if(!istype(chat_update_json)) + return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE]!") + + DecodeChannels(chat_update_json) + return TopicResponse() + if(DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE) + var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT] + if (!isnum(new_port) || !(new_port > 0)) + return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]") + + server_port = new_port + return TopicResponse() + if(DMAPI5_TOPIC_COMMAND_HEARTBEAT) + return TopicResponse() + if(DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH) + var/new_version_string = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION] + if (!istext(new_version_string)) + return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]]") + + var/datum/tgs_version/new_version = new(new_version_string) + if (event_handler) + event_handler.HandleEvent(TGS_EVENT_WATCHDOG_REATTACH, new_version) + + version = new_version + + return TopicResponse() + + return TopicResponse("Unknown command: [command]") + +/datum/tgs_api/v5/proc/Bridge(command, list/data) + if(!data) + data = list() + + data[DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE] = command + data[DMAPI5_PARAMETER_ACCESS_IDENTIFIER] = access_identifier + + var/json = json_encode(data) + var/encoded_json = url_encode(json) + + // This is an infinite sleep until we get a response + var/export_response = world.Export("http://127.0.0.1:[server_port]/Bridge?[DMAPI5_BRIDGE_DATA]=[encoded_json]") + if(!export_response) + TGS_ERROR_LOG("Failed export request: [json]") + return + + var/response_json = file2text(export_response["CONTENT"]) + if(!response_json) + TGS_ERROR_LOG("Failed export request, missing content!") + return + + var/list/bridge_response = json_decode(response_json) + if(!bridge_response) + TGS_ERROR_LOG("Failed export request, bad json: [response_json]") + return + + var/error = bridge_response[DMAPI5_RESPONSE_ERROR_MESSAGE] + if(error) + TGS_ERROR_LOG("Failed export request, bad request: [error]") + return + + return bridge_response + +/datum/tgs_api/v5/OnReboot() + var/list/result = Bridge(DMAPI5_BRIDGE_COMMAND_REBOOT) + if(!result) + return + + //okay so the standard TGS4 proceedure is: right before rebooting change the port to whatever was sent to us in the above json's data parameter + + var/port = result[DMAPI5_BRIDGE_RESPONSE_NEW_PORT] + if(!isnum(port)) + return //this is valid, server may just want use to reboot + + if(port == 0) + //to byond 0 means any port and "none" means close vOv + port = "none" + + if(!world.OpenPort(port)) + TGS_ERROR_LOG("Unable to set port to [port]!") + +/datum/tgs_api/v5/InstanceName() + RequireInitialBridgeResponse() + return instance_name + +/datum/tgs_api/v5/TestMerges() + RequireInitialBridgeResponse() + return test_merges + +/datum/tgs_api/v5/EndProcess() + Bridge(DMAPI5_BRIDGE_COMMAND_KILL) + +/datum/tgs_api/v5/Revision() + RequireInitialBridgeResponse() + return revision + +/datum/tgs_api/v5/ChatBroadcast(message, list/channels) + if(!length(channels)) + channels = ChatChannelInfo() + + var/list/ids = list() + for(var/I in channels) + var/datum/tgs_chat_channel/channel = I + ids += channel.id + + message = list(DMAPI5_CHAT_MESSAGE_TEXT = message, DMAPI5_CHAT_MESSAGE_CHANNEL_IDS = ids) + if(intercepted_message_queue) + intercepted_message_queue += list(message) + else + Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message)) + +/datum/tgs_api/v5/ChatTargetedBroadcast(message, admin_only) + var/list/channels = list() + for(var/I in ChatChannelInfo()) + var/datum/tgs_chat_channel/channel = I + if (!channel.is_private_channel && ((channel.is_admin_channel && admin_only) || (!channel.is_admin_channel && !admin_only))) + channels += channel.id + message = list(DMAPI5_CHAT_MESSAGE_TEXT = message, DMAPI5_CHAT_MESSAGE_CHANNEL_IDS = channels) + if(intercepted_message_queue) + intercepted_message_queue += list(message) + else + Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message)) + +/datum/tgs_api/v5/ChatPrivateMessage(message, datum/tgs_chat_user/user) + message = list(DMAPI5_CHAT_MESSAGE_TEXT = message, DMAPI5_CHAT_MESSAGE_CHANNEL_IDS = list(user.channel.id)) + if(intercepted_message_queue) + intercepted_message_queue += list(message) + else + Bridge(DMAPI5_BRIDGE_COMMAND_CHAT_SEND, list(DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE = message)) + +/datum/tgs_api/v5/ChatChannelInfo() + RequireInitialBridgeResponse() + return chat_channels + +/datum/tgs_api/v5/proc/DecodeChannels(chat_update_json) + var/list/chat_channels_json = chat_update_json[DMAPI5_CHAT_UPDATE_CHANNELS] + if(istype(chat_channels_json)) + chat_channels.Cut() + for(var/channel_json in chat_channels_json) + var/datum/tgs_chat_channel/channel = DecodeChannel(channel_json) + if(channel) + chat_channels += channel + else + TGS_WARNING_LOG("Failed to decode [DMAPI5_CHAT_UPDATE_CHANNELS] from channel update!") + +/datum/tgs_api/v5/proc/DecodeChannel(channel_json) + var/datum/tgs_chat_channel/channel = new + channel.id = channel_json[DMAPI5_CHAT_CHANNEL_ID] + channel.friendly_name = channel_json[DMAPI5_CHAT_CHANNEL_FRIENDLY_NAME] + channel.connection_name = channel_json[DMAPI5_CHAT_CHANNEL_CONNECTION_NAME] + channel.is_admin_channel = channel_json[DMAPI5_CHAT_CHANNEL_IS_ADMIN_CHANNEL] + channel.is_private_channel = channel_json[DMAPI5_CHAT_CHANNEL_IS_PRIVATE_CHANNEL] + channel.custom_tag = channel_json[DMAPI5_CHAT_CHANNEL_TAG] + return channel + +/datum/tgs_api/v5/SecurityLevel() + RequireInitialBridgeResponse() + return security_level + +/* +The MIT License + +Copyright (c) 2020 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgs/v5/commands.dm b/code/modules/tgs/v5/commands.dm new file mode 100644 index 0000000000..2775157656 --- /dev/null +++ b/code/modules/tgs/v5/commands.dm @@ -0,0 +1,68 @@ +/datum/tgs_api/v5/proc/ListCustomCommands() + var/results = list() + custom_commands = list() + for(var/I in typesof(/datum/tgs_chat_command) - /datum/tgs_chat_command) + var/datum/tgs_chat_command/stc = new I + var/command_name = stc.name + if(!command_name || findtext(command_name, " ") || findtext(command_name, "'") || findtext(command_name, "\"")) + TGS_WARNING_LOG("Custom command [command_name] ([I]) can't be used as it is empty or contains illegal characters!") + continue + + if(results[command_name]) + var/datum/other = custom_commands[command_name] + TGS_WARNING_LOG("Custom commands [other.type] and [I] have the same name (\"[command_name]\"), only [other.type] will be available!") + continue + results += list(list(DMAPI5_CUSTOM_CHAT_COMMAND_NAME = command_name, DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT = stc.help_text, DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY = stc.admin_only)) + custom_commands[command_name] = stc + + return results + +/datum/tgs_api/v5/proc/HandleCustomCommand(list/command_json) + var/command = command_json[DMAPI5_CHAT_COMMAND_NAME] + var/user = command_json[DMAPI5_CHAT_COMMAND_USER] + var/params = command_json[DMAPI5_CHAT_COMMAND_PARAMS] + + var/datum/tgs_chat_user/u = new + u.id = user[DMAPI5_CHAT_USER_ID] + u.friendly_name = user[DMAPI5_CHAT_USER_FRIENDLY_NAME] + u.mention = user[DMAPI5_CHAT_USER_MENTION] + u.channel = DecodeChannel(user[DMAPI5_CHAT_USER_CHANNEL]) + + var/datum/tgs_chat_command/sc = custom_commands[command] + if(sc) + var/text_response = sc.Run(u, params) + var/list/topic_response = list() + if(!istext(text_response)) + TGS_ERROR_LOG("Custom command [command] should return a string! Got: \"[text_response]\"") + text_response = null + topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE] = text_response + return json_encode(topic_response) + return TopicResponse("Unknown custom chat command: [command]!") + +/* + +The MIT License + +Copyright (c) 2020 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgs/v5/undef.dm b/code/modules/tgs/v5/undef.dm new file mode 100644 index 0000000000..b27e3abe95 --- /dev/null +++ b/code/modules/tgs/v5/undef.dm @@ -0,0 +1,124 @@ +#undef DMAPI5_PARAM_SERVER_PORT +#undef DMAPI5_PARAM_ACCESS_IDENTIFIER + +#undef DMAPI5_BRIDGE_DATA +#undef DMAPI5_TOPIC_DATA + +#undef DMAPI5_BRIDGE_COMMAND_PORT_UPDATE +#undef DMAPI5_BRIDGE_COMMAND_STARTUP +#undef DMAPI5_BRIDGE_COMMAND_PRIME +#undef DMAPI5_BRIDGE_COMMAND_REBOOT +#undef DMAPI5_BRIDGE_COMMAND_KILL +#undef DMAPI5_BRIDGE_COMMAND_CHAT_SEND + +#undef DMAPI5_PARAMETER_ACCESS_IDENTIFIER +#undef DMAPI5_RESPONSE_ERROR_MESSAGE + +#undef DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE +#undef DMAPI5_BRIDGE_PARAMETER_CURRENT_PORT +#undef DMAPI5_BRIDGE_PARAMETER_VERSION +#undef DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE +#undef DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS +#undef DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL + +#undef DMAPI5_BRIDGE_RESPONSE_NEW_PORT +#undef DMAPI5_BRIDGE_RESPONSE_RUNTIME_INFORMATION + +#undef DMAPI5_CHAT_MESSAGE_TEXT +#undef DMAPI5_CHAT_MESSAGE_CHANNEL_IDS + +#undef DMAPI5_RUNTIME_INFORMATION_ACCESS_IDENTIFIER +#undef DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION +#undef DMAPI5_RUNTIME_INFORMATION_SERVER_PORT +#undef DMAPI5_RUNTIME_INFORMATION_API_VALIDATE_ONLY +#undef DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME +#undef DMAPI5_RUNTIME_INFORMATION_REVISION +#undef DMAPI5_RUNTIME_INFORMATION_TEST_MERGES +#undef DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL + +#undef DMAPI5_CHAT_UPDATE_CHANNELS + +#undef DMAPI5_TEST_MERGE_TIME_MERGED +#undef DMAPI5_TEST_MERGE_REVISION +#undef DMAPI5_TEST_MERGE_TITLE_AT_MERGE +#undef DMAPI5_TEST_MERGE_BODY_AT_MERGE +#undef DMAPI5_TEST_MERGE_URL +#undef DMAPI5_TEST_MERGE_AUTHOR +#undef DMAPI5_TEST_MERGE_NUMBER +#undef DMAPI5_TEST_MERGE_PULL_REQUEST_REVISION +#undef DMAPI5_TEST_MERGE_COMMENT + +#undef DMAPI5_CHAT_COMMAND_NAME +#undef DMAPI5_CHAT_COMMAND_PARAMS +#undef DMAPI5_CHAT_COMMAND_USER + +#undef DMAPI5_EVENT_NOTIFICATION_TYPE +#undef DMAPI5_EVENT_NOTIFICATION_PARAMETERS + +#undef DMAPI5_TOPIC_COMMAND_CHAT_COMMAND +#undef DMAPI5_TOPIC_COMMAND_EVENT_NOTIFICATION +#undef DMAPI5_TOPIC_COMMAND_CHANGE_PORT +#undef DMAPI5_TOPIC_COMMAND_CHANGE_REBOOT_STATE +#undef DMAPI5_TOPIC_COMMAND_INSTANCE_RENAMED +#undef DMAPI5_TOPIC_COMMAND_CHAT_CHANNELS_UPDATE +#undef DMAPI5_TOPIC_COMMAND_SERVER_PORT_UPDATE +#undef DMAPI5_TOPIC_COMMAND_HEARTBEAT +#undef DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH + +#undef DMAPI5_TOPIC_PARAMETER_COMMAND_TYPE +#undef DMAPI5_TOPIC_PARAMETER_CHAT_COMMAND +#undef DMAPI5_TOPIC_PARAMETER_EVENT_NOTIFICATION +#undef DMAPI5_TOPIC_PARAMETER_NEW_PORT +#undef DMAPI5_TOPIC_PARAMETER_NEW_REBOOT_STATE +#undef DMAPI5_TOPIC_PARAMETER_NEW_INSTANCE_NAME +#undef DMAPI5_TOPIC_PARAMETER_CHAT_UPDATE +#undef DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION + +#undef DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE +#undef DMAPI5_TOPIC_RESPONSE_CHAT_RESPONSES + +#undef DMAPI5_REVISION_INFORMATION_COMMIT_SHA +#undef DMAPI5_REVISION_INFORMATION_ORIGIN_COMMIT_SHA + +#undef DMAPI5_CHAT_USER_ID +#undef DMAPI5_CHAT_USER_FRIENDLY_NAME +#undef DMAPI5_CHAT_USER_MENTION +#undef DMAPI5_CHAT_USER_CHANNEL + +#undef DMAPI5_CHAT_CHANNEL_ID +#undef DMAPI5_CHAT_CHANNEL_FRIENDLY_NAME +#undef DMAPI5_CHAT_CHANNEL_CONNECTION_NAME +#undef DMAPI5_CHAT_CHANNEL_IS_ADMIN_CHANNEL +#undef DMAPI5_CHAT_CHANNEL_IS_PRIVATE_CHANNEL +#undef DMAPI5_CHAT_CHANNEL_TAG + +#undef DMAPI5_CUSTOM_CHAT_COMMAND_NAME +#undef DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT +#undef DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY + +/* +The MIT License + +Copyright (c) 2020 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ diff --git a/code/modules/tgui/states.dm b/code/modules/tgui/states.dm index b0808cef5e..723e5f90ed 100644 --- a/code/modules/tgui/states.dm +++ b/code/modules/tgui/states.dm @@ -99,7 +99,7 @@ * return UI_state The state of the UI. **/ /mob/living/proc/shared_living_ui_distance(atom/movable/src_object) - if(!(src_object in view(src))) // If the object is obscured, close it. + if(!(src_object in fov_view())) // If the object is obscured, close it. return UI_CLOSE var/dist = get_dist(src_object, src) diff --git a/code/modules/tgui/states/physical.dm b/code/modules/tgui/states/physical.dm index a4cea7c7c2..3b13dc5b3d 100644 --- a/code/modules/tgui/states/physical.dm +++ b/code/modules/tgui/states/physical.dm @@ -2,7 +2,7 @@ * tgui state: physical_state * * Short-circuits the default state to only check physical distance. - **/ + */ GLOBAL_DATUM_INIT(physical_state, /datum/ui_state/physical, new) @@ -22,3 +22,28 @@ GLOBAL_DATUM_INIT(physical_state, /datum/ui_state/physical, new) /mob/living/silicon/ai/physical_can_use_topic(src_object) return UI_UPDATE // AIs are not physical. + +/** + * tgui state: physical_obscured_state + * + * Short-circuits the default state to only check physical distance, being in view doesn't matter + */ + +GLOBAL_DATUM_INIT(physical_obscured_state, /datum/ui_state/physical_obscured_state, new) + +/datum/ui_state/physical_obscured_state/can_use_topic(src_object, mob/user) + . = user.shared_ui_interaction(src_object) + if(. > UI_CLOSE) + return min(., user.physical_obscured_can_use_topic(src_object)) + +/mob/proc/physical_obscured_can_use_topic(src_object) + return UI_CLOSE + +/mob/living/physical_obscured_can_use_topic(src_object) + return shared_living_ui_distance(src_object) + +/mob/living/silicon/physical_obscured_can_use_topic(src_object) + return max(UI_UPDATE, shared_living_ui_distance(src_object)) // Silicons can always see. + +/mob/living/silicon/ai/physical_obscured_can_use_topic(src_object) + return UI_UPDATE // AIs are not physical. \ No newline at end of file diff --git a/code/modules/uplink/uplink_items/uplink_badass.dm b/code/modules/uplink/uplink_items/uplink_badass.dm index 840f100611..43e5523bad 100644 --- a/code/modules/uplink/uplink_items/uplink_badass.dm +++ b/code/modules/uplink/uplink_items/uplink_badass.dm @@ -51,6 +51,7 @@ manufactured to pack a little bit more of a punch if your client needs some convincing." item = /obj/item/storage/secure/briefcase/syndie cost = 1 + restricted = TRUE /datum/uplink_item/badass/syndiecards name = "Syndicate Playing Cards" diff --git a/code/modules/uplink/uplink_items/uplink_bundles.dm b/code/modules/uplink/uplink_items/uplink_bundles.dm index 478be5960e..321b9121bc 100644 --- a/code/modules/uplink/uplink_items/uplink_bundles.dm +++ b/code/modules/uplink/uplink_items/uplink_bundles.dm @@ -40,6 +40,7 @@ cost = 20 player_minimum = 30 exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) + restricted = TRUE /datum/uplink_item/bundles_TC/northstar_bundle name = "Northstar Bundle" diff --git a/code/modules/uplink/uplink_items/uplink_devices.dm b/code/modules/uplink/uplink_items/uplink_devices.dm index cda83cf684..2d20fd0b7b 100644 --- a/code/modules/uplink/uplink_items/uplink_devices.dm +++ b/code/modules/uplink/uplink_items/uplink_devices.dm @@ -201,10 +201,9 @@ /datum/uplink_item/device_tools/stimpack name = "Stimpack" desc = "Stimpacks, the tool of many great heroes, make you nearly immune to stuns and knockdowns for about \ - 5 minutes after fully injecting yourself. Can inject yourself, or others, 5 times and through hardsuits. \ - Each injection will gives around a minute of stimulants." - item = /obj/item/reagent_containers/hypospray/medipen/stimulants - cost = 5 + 5 minutes after injection." + item = /obj/item/reagent_containers/syringe/stimulants + cost = 3 surplus = 90 /datum/uplink_item/device_tools/medkit @@ -272,3 +271,15 @@ cost = 2 include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) restricted = TRUE + +/* for now +/datum/uplink_item/device_tools/suspiciousphone + name = "Protocol CRAB-17 Phone" + desc = "The Protocol CRAB-17 Phone, a phone borrowed from an unknown third party, it can be used to crash the space market, funneling the losses of the crew to your bank account.\ + The crew can move their funds to a new banking site though, unless they HODL, in which case they deserve it." + item = /obj/item/suspiciousphone + cost = 7 + restricted = TRUE + limited_stock = 1 +*/ + diff --git a/code/modules/vehicles/bicycle.dm b/code/modules/vehicles/bicycle.dm index 84e0fcbefc..3784f4d459 100644 --- a/code/modules/vehicles/bicycle.dm +++ b/code/modules/vehicles/bicycle.dm @@ -24,10 +24,12 @@ buckled_mob.stop_sound_channel(CHANNEL_BICYCLE) . =..() -/obj/vehicle/ridden/bicycle/tesla_act() // :::^^^))) +/obj/vehicle/ridden/bicycle/zap_act(zap_str, zap_flags, shocked_targets) // :::^^^))) + //This didn't work for 3 years because none ever tested it I hate life name = "fried bicycle" desc = "Well spent." color = rgb(63, 23, 4) can_buckle = FALSE + . = ..() for(var/m in buckled_mobs) unbuckle_mob(m,1) diff --git a/code/modules/vehicles/ridden.dm b/code/modules/vehicles/ridden.dm index 4f3970dd37..f71d9367d3 100644 --- a/code/modules/vehicles/ridden.dm +++ b/code/modules/vehicles/ridden.dm @@ -77,3 +77,7 @@ if(!force && occupant_amount() >= max_occupants) return FALSE return ..() + +/obj/vehicle/ridden/zap_act(zap_str, zap_flags, shocked_targets) + zap_buckle_check(zap_str) + . = ..() diff --git a/code/modules/vehicles/sealed.dm b/code/modules/vehicles/sealed.dm index fc81e2ec00..edaab8b982 100644 --- a/code/modules/vehicles/sealed.dm +++ b/code/modules/vehicles/sealed.dm @@ -1,5 +1,6 @@ /obj/vehicle/sealed var/enter_delay = 20 + flags_1 = BLOCK_FACE_ATOM_1 /obj/vehicle/sealed/generate_actions() . = ..() @@ -51,7 +52,7 @@ if(randomstep) var/turf/target_turf = get_step(exit_location(M), pick(GLOB.cardinals)) M.throw_at(target_turf, 5, 10) - + if(!silent) M.visible_message("[M] drops out of \the [src]!") return TRUE @@ -102,7 +103,13 @@ if(iscarbon(i)) var/mob/living/carbon/C = i C.DefaultCombatKnockdown(40) - - + + /obj/vehicle/sealed/AllowDrop() return FALSE + +/obj/vehicle/sealed/setDir(newdir) + . = ..() + for(var/k in occupants) + var/mob/M = k + M.setDir(newdir) diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm index 5a96a92f07..6e6636cd62 100644 --- a/code/modules/vending/_vending.dm +++ b/code/modules/vending/_vending.dm @@ -30,6 +30,10 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C var/amount = 0 ///How many we can store at maximum var/max_amount = 0 + ///Does the item have a custom price override + var/custom_price + ///Does the item have a custom premium price override + var/custom_premium_price /** * # vending machines @@ -50,6 +54,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C integrity_failure = 0.33 armor = list("melee" = 20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70) circuit = /obj/item/circuitboard/machine/vendor + payment_department = ACCOUNT_SRV light_power = 0.5 light_range = MINIMUM_USEFUL_LIGHT_RANGE /// Is the machine active (No sales pitches if off)! @@ -118,11 +123,13 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C var/extended_inventory ///Are we checking the users ID var/scan_id = TRUE - ///Coins that we accept? var/obj/item/coin/coin - ///Bills that we accept? - var/obj/item/stack/spacecash/bill ///Default price of items if not overridden + var/default_price = 25 + ///Default price of premium items if not overridden + var/extra_price = 50 + ///cost multiplier per department or access + var/list/cost_multiplier_per_dept = list() /** * Is this item on station or not * @@ -144,7 +151,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C var/obj/item/vending_refill/refill_canister = null /// how many items have been inserted in a vendor - var/loaded_items + var/loaded_items = 0 ///Name of lighting mask for the vending machine var/light_mask @@ -180,11 +187,18 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C // so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is crated. last_slogan = world.time + rand(0, slogan_delay) power_change() + if(onstation_override) //overrides the checks if true. + onstation = TRUE + return + if(mapload && !is_station_level(z)) //check if it was initially created off station during mapload. + onstation = FALSE + if(circuit) + circuit.onstation = onstation //sync up the circuit so the pricing schema is carried over if it's reconstructed. + else if(circuit && (circuit.onstation != onstation)) //check if they're not the same to minimize the amount of edited values. + onstation = circuit.onstation //if it was constructed outside mapload, sync the vendor up with the circuit's var so you can't bypass price requirements by moving / reconstructing it off station. /obj/machinery/vending/Destroy() QDEL_NULL(wires) - QDEL_NULL(coin) - QDEL_NULL(bill) return ..() /obj/machinery/vending/can_speak() @@ -284,6 +298,8 @@ GLOBAL_LIST_EMPTY(vending_products) if(!start_empty) R.amount = amount R.max_amount = amount + R.custom_price = initial(temp.custom_price) + R.custom_premium_price = initial(temp.custom_premium_price) recordlist += R /** * Refill a vending machine from a refill canister @@ -375,39 +391,7 @@ GLOBAL_LIST_EMPTY(vending_products) if(panel_open && is_wire_tool(I)) wires.interact(user) return - else if(istype(I, /obj/item/coin)) - if(coin) - to_chat(user, "[src] already has [coin] inserted") - return - if(bill) - to_chat(user, "[src] already has [bill] inserted") - return - if(!premium.len) - to_chat(user, "[src] doesn't have a coin slot.") - return - if(!user.transferItemToLoc(I, src)) - return - coin = I - to_chat(user, "You insert [I] into [src].") - return - else if(istype(I, /obj/item/stack/spacecash)) - if(coin) - to_chat(user, "[src] already has [coin] inserted") - return - if(bill) - to_chat(user, "[src] already has [bill] inserted") - return - if(!premium.len) - to_chat(user, "[src] doesn't have a bill slot.") - return - if(!user.transferItemToLoc(I, src)) - return - var/obj/item/stack/S = I - S.use(1) - bill = new S.type(src, 1) - to_chat(user, "You insert [I] into [src].") - return - else if(refill_canister && istype(I, refill_canister)) + if(refill_canister && istype(I, refill_canister)) if (!panel_open) to_chat(user, "You should probably unscrew the service panel first!") else if (stat & (BROKEN|NOPOWER)) @@ -543,11 +527,13 @@ GLOBAL_LIST_EMPTY(vending_products) /obj/machinery/vending/ui_static_data(mob/user) . = list() + .["onstation"] = onstation .["product_records"] = list() for (var/datum/data/vending_product/R in product_records) var/list/data = list( path = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-"), name = R.name, + price = R.custom_price || default_price, max_amount = R.max_amount, ref = REF(R) ) @@ -557,6 +543,7 @@ GLOBAL_LIST_EMPTY(vending_products) var/list/data = list( path = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-"), name = R.name, + price = R.custom_premium_price || extra_price, max_amount = R.max_amount, ref = REF(R), premium = TRUE @@ -567,6 +554,7 @@ GLOBAL_LIST_EMPTY(vending_products) var/list/data = list( path = replacetext(replacetext("[R.product_path]", "/obj/item/", ""), "/", "-"), name = R.name, + price = R.custom_price || default_price, max_amount = R.max_amount, ref = REF(R), premium = TRUE @@ -575,12 +563,29 @@ GLOBAL_LIST_EMPTY(vending_products) /obj/machinery/vending/ui_data(mob/user) . = list() + var/obj/item/card/id/C = user.get_idcard(TRUE) + .["cost_mult"] = 1 + .["cost_text"] = "" + if(C && C.registered_account) + .["user"] = list() + .["user"]["name"] = C.registered_account.account_holder + .["user"]["cash"] = C.registered_account.account_balance + if(C.registered_account.account_job) + .["user"]["job"] = C.registered_account.account_job.title + else + .["user"]["job"] = "No Job" + var/cost_mult = get_best_discount(C) + if(cost_mult != 1) + .["cost_mult"] = cost_mult + if(cost_mult < 1) + .["cost_text"] = " ([(1 - cost_mult) * 100]% OFF)" + else + .["cost_text"] = " ([(cost_mult - 1) * 100]% EXTRA)" .["stock"] = list() - for(var/datum/data/vending_product/R in product_records + coin_records + hidden_records) + for (var/datum/data/vending_product/R in product_records + coin_records + hidden_records) .["stock"][R.name] = R.amount + . .["extended_inventory"] = extended_inventory - .["coin"] = coin - .["bill"] = bill /obj/machinery/vending/ui_act(action, params) . = ..() @@ -594,75 +599,69 @@ GLOBAL_LIST_EMPTY(vending_products) if(panel_open) to_chat(usr, "The vending machine cannot dispense products while its service panel is open!") return - if((!allowed(usr)) && !(obj_flags & EMAGGED) && scan_id) //For SECURE VENDING MACHINES YEAH - to_chat(usr, "Access denied." ) - flick(icon_deny,src) - return vend_ready = FALSE //One thing at a time!! var/datum/data/vending_product/R = locate(params["ref"]) + var/list/record_to_check = product_records + coin_records + if(extended_inventory) + record_to_check = product_records + coin_records + hidden_records if(!R || !istype(R) || !R.product_path) vend_ready = TRUE return - if(R.amount <= 0) - to_chat(usr, "Sold out.") - vend_ready = TRUE - return + var/price_to_use = R.custom_price || default_price if(R in hidden_records) if(!extended_inventory) vend_ready = TRUE return - else if(R in coin_records) - if(!(coin || bill)) - to_chat(usr, "You need to insert a coin to get this item!") - vend_ready = TRUE - return - if(coin && coin.string_attached) - if(prob(50)) - if(usr.put_in_hands(coin)) - to_chat(usr, "You successfully pull [coin] out before [src] could swallow it.") - coin = null - else - to_chat(usr, "You couldn't pull [coin] out because your hands are full!") - QDEL_NULL(coin) - else - to_chat(usr, "You weren't able to pull [coin] out fast enough, the machine ate it, string and all!") - QDEL_NULL(coin) - else - QDEL_NULL(coin) - QDEL_NULL(bill) - else if(!(R in product_records)) + else if (!(R in record_to_check)) vend_ready = TRUE message_admins("Vending machine exploit attempted by [ADMIN_LOOKUPFLW(usr)]!") return - if(((last_reply + 200) <= world.time) && vend_reply) - speak(vend_reply) - last_reply = world.time + if (R.amount <= 0) + say("Sold out of [R.name].") + flick(icon_deny,src) + vend_ready = TRUE + return + if(onstation && price_to_use >= 0) + var/obj/item/card/id/C = usr.get_idcard(TRUE) + if(!C) + say("No card found.") + flick(icon_deny,src) + vend_ready = TRUE + return + else if (!C.registered_account) + say("No account found.") + flick(icon_deny,src) + vend_ready = TRUE + return + var/datum/bank_account/account = C.registered_account + if(coin_records.Find(R)) + price_to_use = R.custom_premium_price || extra_price + else if(!hidden_records.Find(R)) + price_to_use = round(price_to_use * get_best_discount(C)) + if(price_to_use && !account.adjust_money(-price_to_use)) + say("You do not possess the funds to purchase [R.name].") + flick(icon_deny,src) + vend_ready = TRUE + return + var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department) + if(D) + D.adjust_money(price_to_use) + if(last_shopper != usr || purchase_message_cooldown < world.time) + say("Thank you for shopping with [src]!") + purchase_message_cooldown = world.time + 5 SECONDS + last_shopper = usr use_power(5) if(icon_vend) //Show the vending animation if needed flick(icon_vend,src) - var/vended = new R.product_path(get_turf(src)) + playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3) + var/obj/item/vended = new R.product_path(get_turf(src)) + R.amount-- if(usr.CanReach(src) && usr.put_in_hands(vended)) to_chat(usr, "You take [R.name] out of the slot.") else to_chat(usr, "[capitalize(R.name)] falls onto the floor!") - R.amount-- SSblackbox.record_feedback("nested tally", "vending_machine_usage", 1, list("[type]", "[R.product_path]")) vend_ready = TRUE - return - if("takeoutcoin") - usr.put_in_hands(coin) - to_chat(usr, "You remove [coin] from [src].") - coin = null - return - if("takeoutbill") - usr.put_in_hands(bill) - to_chat(usr, "You remove [bill] from [src].") - bill = null - return - - if("togglevoice") - if(panel_open) - shut_up = !shut_up /obj/machinery/vending/process() if(stat & (BROKEN|NOPOWER)) @@ -697,6 +696,25 @@ GLOBAL_LIST_EMPTY(vending_products) say(message) +/** + * Gets the best discount from a given ID card, comparing its access and paycheck depart with cost_multiplier_per_dept. + * It only applies to the regular selection, not premium or contraband. And a bank account is still required. + * But it can also be used to charge more to certain departments or accesses. :) + * + * Arguments: + * * list/dept_access_list - the list to compare + */ +/obj/machinery/vending/proc/get_best_discount(obj/item/card/id/C) + var/list/discounts = NUMLIST2TEXTLIST(C.GetAccess()) + if(C.registered_account?.account_job) + discounts += C.registered_account.account_job.paycheck_department + discounts &= cost_multiplier_per_dept + if(!length(discounts)) + return 1 + . = INFINITY + for(var/k in discounts) + . = min(cost_multiplier_per_dept[k], .) + /obj/machinery/vending/power_change() . = ..() if(powered()) @@ -774,3 +792,196 @@ GLOBAL_LIST_EMPTY(vending_products) /obj/machinery/vending/onTransitZ() return + +/obj/machinery/vending/custom + name = "Custom Vendor" + icon_state = "robotics" + icon_deny = "robotics-deny" + max_integrity = 400 + payment_department = NO_FREEBIES + refill_canister = /obj/item/vending_refill/custom + /// where the money is sent + var/datum/bank_account/private_a + /// max number of items that the custom vendor can hold + var/max_loaded_items = 20 + /// Base64 cache of custom icons. + var/list/base64_cache = list() + +/obj/machinery/vending/custom/compartmentLoadAccessCheck(mob/user) + . = FALSE + var/mob/living/carbon/human/H + var/obj/item/card/id/C + if(ishuman(user)) + H = user + C = H.get_idcard(FALSE) + if(C?.registered_account && C.registered_account == private_a) + return TRUE + +/obj/machinery/vending/custom/canLoadItem(obj/item/I, mob/user) + . = FALSE + if(loaded_items >= max_loaded_items) + say("There are too many items in stock.") + return + if(istype(I, /obj/item/stack)) + say("Loose items may cause problems, try use it inside wrapping paper.") + return + if(I.custom_price) + return TRUE + +/obj/machinery/vending/custom/ui_data(mob/user) + . = ..() + .["access"] = compartmentLoadAccessCheck(user) + .["vending_machine_input"] = list() + for (var/O in vending_machine_input) + if(vending_machine_input[O] > 0) + var/base64 + var/price = 0 + for(var/obj/T in contents) + if(T.name == O) + price = T.custom_price + if(!base64) + if(base64_cache[T.type]) + base64 = base64_cache[T.type] + else + base64 = icon2base64(icon(T.icon, T.icon_state)) + base64_cache[T.type] = base64 + break + var/list/data = list( + name = O, + price = price, + img = base64 + ) + .["vending_machine_input"] += list(data) + +/obj/machinery/vending/custom/ui_act(action, params) + . = ..() + if(.) + return + switch(action) + if("dispense") + . = TRUE + if(!vend_ready) + return + var/N = params["item"] + var/obj/S + vend_ready = FALSE + if(ishuman(usr)) + var/mob/living/carbon/human/H = usr + var/obj/item/card/id/C = H.get_idcard(TRUE) + + if(!C) + say("No card found.") + flick(icon_deny,src) + vend_ready = TRUE + return + else if (!C.registered_account) + say("No account found.") + flick(icon_deny,src) + vend_ready = TRUE + return + var/datum/bank_account/account = C.registered_account + for(var/obj/O in contents) + if(O.name == N) + S = O + break + if(S) + if(compartmentLoadAccessCheck(usr)) + vending_machine_input[N] = max(vending_machine_input[N] - 1, 0) + S.forceMove(drop_location()) + loaded_items-- + use_power(5) + vend_ready = TRUE + updateUsrDialog() + return + if(account.has_money(S.custom_price)) + account.adjust_money(-S.custom_price) + var/datum/bank_account/owner = private_a + if(owner) + owner.adjust_money(S.custom_price) + vending_machine_input[N] = max(vending_machine_input[N] - 1, 0) + S.forceMove(drop_location()) + loaded_items-- + use_power(5) + if(last_shopper != usr || purchase_message_cooldown < world.time) + say("Thank you for buying local and purchasing [S]!") + purchase_message_cooldown = world.time + 5 SECONDS + last_shopper = usr + vend_ready = TRUE + updateUsrDialog() + return + else + say("You do not possess the funds to purchase this.") + vend_ready = TRUE + +/obj/machinery/vending/custom/attackby(obj/item/I, mob/user, params) + if(!private_a) + var/mob/living/carbon/human/H + var/obj/item/card/id/C + if(ishuman(user)) + H = user + C = H.get_idcard(TRUE) + if(C?.registered_account) + private_a = C.registered_account + say("\The [src] has been linked to [C].") + + if(compartmentLoadAccessCheck(user)) + if(istype(I, /obj/item/pen)) + name = stripped_input(user,"Set name","Name", name, 20) + desc = stripped_input(user,"Set description","Description", desc, 60) + slogan_list += stripped_input(user,"Set slogan","Slogan","Epic", 60) + last_slogan = world.time + rand(0, slogan_delay) + return + + if(canLoadItem(I)) + loadingAttempt(I,user) + updateUsrDialog() + return + + if(panel_open && is_wire_tool(I)) + wires.interact(user) + return + + return ..() + +/obj/machinery/vending/custom/crowbar_act(mob/living/user, obj/item/I) + return FALSE + +/obj/machinery/vending/custom/Destroy() + unbuckle_all_mobs(TRUE) + var/turf/T = get_turf(src) + if(T) + for(var/obj/item/I in contents) + I.forceMove(T) + explosion(T, -1, 0, 3) + return ..() + +/obj/machinery/vending/custom/unbreakable + name = "Indestructible Vendor" + resistance_flags = INDESTRUCTIBLE + +/obj/item/vending_refill/custom + machine_name = "Custom Vendor" + icon_state = "refill_custom" + custom_premium_price = 100 + +/obj/item/price_tagger + name = "price tagger" + desc = "This tool is used to set a price for items used in custom vendors." + icon = 'icons/obj/device.dmi' + icon_state = "pricetagger" + custom_premium_price = 25 + ///the price of the item + var/price = 1 + +/obj/item/price_tagger/attack_self(mob/user) + price = max(1, round(input(user,"set price","price") as num|null, 1)) + to_chat(user, " The [src] will now give things a [price] cr tag.") + +/obj/item/price_tagger/afterattack(atom/target, mob/user, proximity) + . = ..() + if(!proximity) + return + if(isitem(target)) + var/obj/item/I = target + I.custom_price = price + to_chat(user, "You set the price of [I] to [price] cr.") diff --git a/code/modules/vending/assist.dm b/code/modules/vending/assist.dm index 5dafd3935c..25dbee66bc 100644 --- a/code/modules/vending/assist.dm +++ b/code/modules/vending/assist.dm @@ -19,6 +19,9 @@ armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) refill_canister = /obj/item/vending_refill/assist resistance_flags = FIRE_PROOF + default_price = 50 + extra_price = 100 + payment_department = NO_FREEBIES /obj/item/vending_refill/assist icon_state = "refill_engi" \ No newline at end of file diff --git a/code/modules/vending/autodrobe.dm b/code/modules/vending/autodrobe.dm index 2eaf24c493..216b95145d 100644 --- a/code/modules/vending/autodrobe.dm +++ b/code/modules/vending/autodrobe.dm @@ -3,7 +3,6 @@ desc = "A vending machine for costumes." icon_state = "theater" icon_deny = "theater-deny" - req_access = list(ACCESS_THEATRE) product_slogans = "Dress for success!;Suited and booted!;It's show time!;Why leave style up to fate? Use AutoDrobe!" vend_reply = "Thank you for using AutoDrobe!" products = list(/obj/item/clothing/suit/chickensuit = 1, @@ -124,7 +123,7 @@ /obj/item/clothing/shoes/roman = 1, /obj/item/shield/riot/roman/fake = 1, /obj/item/skub = 1, - /obj/item/clothing/under/costume/lobster = 1, // CIT CHANGES + /obj/item/clothing/under/costume/lobster = 1, /obj/item/clothing/head/lobsterhat = 1, /obj/item/clothing/head/drfreezehat = 1, /obj/item/clothing/suit/dracula = 1, @@ -137,12 +136,19 @@ /obj/item/clothing/under/costume/christmas/croptop/green = 3, /obj/item/clothing/head/christmashat = 3, /obj/item/clothing/head/christmashatg = 3, - /obj/item/clothing/under/costume/drfreeze = 1) //End of Cit Changes - refill_canister = /obj/item/vending_refill/autodrobe + /obj/item/clothing/under/costume/drfreeze = 1) -/obj/machinery/vending/autodrobe/all_access - desc = "A vending machine for costumes. This model appears to have no access restrictions." - req_access = null + refill_canister = /obj/item/vending_refill/autodrobe + default_price = 180 + extra_price = 360 + payment_department = ACCOUNT_SRV + +/obj/machinery/vending/autodrobe/Initialize() + . = ..() + cost_multiplier_per_dept = list("[ACCESS_THEATRE]" = 0) + +/obj/machinery/vending/autodrobe/canLoadItem(obj/item/I,mob/user) + return (I.type in products) /obj/item/vending_refill/autodrobe machine_name = "AutoDrobe" diff --git a/code/modules/vending/boozeomat.dm b/code/modules/vending/boozeomat.dm index 5a6380c322..e24813c2e9 100644 --- a/code/modules/vending/boozeomat.dm +++ b/code/modules/vending/boozeomat.dm @@ -4,7 +4,7 @@ icon_state = "boozeomat" icon_deny = "boozeomat-deny" products = list(/obj/item/reagent_containers/food/drinks/drinkingglass = 30, - /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass = 12, + /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass = 12, /obj/item/reagent_containers/food/drinks/bottle/gin = 5, /obj/item/reagent_containers/food/drinks/bottle/whiskey = 5, /obj/item/reagent_containers/food/drinks/bottle/tequila = 5, @@ -39,12 +39,11 @@ /obj/item/reagent_containers/food/drinks/bottle/trappist = 5) product_slogans = "I hope nobody asks me for a bloody cup o' tea...;Alcohol is humanity's friend. Would you abandon a friend?;Quite delighted to serve you!;Is nobody thirsty on this station?" product_ads = "Drink up!;Booze is good for you!;Alcohol is humanity's best friend.;Quite delighted to serve you!;Care for a nice, cold beer?;Nothing cures you like booze!;Have a sip!;Have a drink!;Have a beer!;Beer is good for you!;Only the finest alcohol!;Best quality booze since 2053!;Award-winning wine!;Maximum alcohol!;Man loves beer.;A toast for progress!" - req_access = list(ACCESS_BAR) refill_canister = /obj/item/vending_refill/boozeomat - -/obj/machinery/vending/boozeomat/all_access - desc = "A technological marvel, supposedly able to mix just the mixture you'd like to drink the moment you ask for one. This model appears to have no access restrictions." - req_access = null + default_price = 120 + extra_price = 100 + payment_department = ACCOUNT_SRV + cost_multiplier_per_dept = list(ACCOUNT_SRV = 0) /obj/machinery/vending/boozeomat/pubby_maint //abandoned bar on Pubbystation products = list(/obj/item/reagent_containers/food/drinks/bottle/whiskey = 1, @@ -56,7 +55,6 @@ /obj/item/reagent_containers/food/drinks/ice = 3, /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass = 6, /obj/item/reagent_containers/food/drinks/flask = 1) - req_access = null /obj/machinery/vending/boozeomat/pubby_captain //Captain's quarters on Pubbystation products = list(/obj/item/reagent_containers/food/drinks/bottle/rum = 1, @@ -65,10 +63,17 @@ /obj/item/reagent_containers/food/drinks/drinkingglass = 6, /obj/item/reagent_containers/food/drinks/ice = 1, /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass = 4); - req_access = list(ACCESS_CAPTAIN) + +/obj/machinery/vending/boozeomat/pubby_captain/Initialize() + . = ..() + cost_multiplier_per_dept = list("[ACCESS_CAPTAIN]" = 0) /obj/machinery/vending/boozeomat/syndicate_access - req_access = list(ACCESS_SYNDICATE) + payment_department = NO_FREEBIES + +/obj/machinery/vending/boozeomat/syndicate_access/Initialize() + . = ..() + cost_multiplier_per_dept = list("[ACCESS_SYNDICATE]" = 0) /obj/item/vending_refill/boozeomat machine_name = "Booze-O-Mat" diff --git a/code/modules/vending/cartridge.dm b/code/modules/vending/cartridge.dm index 35b1a1da7a..79380ca1f3 100644 --- a/code/modules/vending/cartridge.dm +++ b/code/modules/vending/cartridge.dm @@ -16,6 +16,10 @@ armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) refill_canister = /obj/item/vending_refill/cart resistance_flags = FIRE_PROOF + default_price = 250 + extra_price = 500 + payment_department = ACCOUNT_SRV + cost_multiplier_per_dept = list(ACCOUNT_SRV = 0) /obj/item/vending_refill/cart icon_state = "refill_pda" diff --git a/code/modules/vending/cigarette.dm b/code/modules/vending/cigarette.dm index f567c9765e..6f535b2c6d 100644 --- a/code/modules/vending/cigarette.dm +++ b/code/modules/vending/cigarette.dm @@ -20,6 +20,9 @@ /obj/item/storage/fancy/cigarettes/cigars/havana = 1, /obj/item/storage/fancy/cigarettes/cigars/cohiba = 1) refill_canister = /obj/item/vending_refill/cigarette + default_price = 75 + extra_price = 250 + payment_department = ACCOUNT_SRV /obj/machinery/vending/cigarette/syndicate products = list(/obj/item/storage/fancy/cigarettes/cigpack_syndicate = 7, @@ -30,6 +33,11 @@ /obj/item/storage/box/matches = 10, /obj/item/lighter/greyscale = 4, /obj/item/storage/fancy/rollingpapers = 5) + payment_department = NO_FREEBIES + +/obj/machinery/vending/cigarette/syndicate/Initialize() + . = ..() + cost_multiplier_per_dept = list("[ACCESS_SYNDICATE]" = 0) /obj/machinery/vending/cigarette/beach //Used in the lavaland_biodome_beach.dmm ruin name = "\improper ShadyCigs Ultra" diff --git a/code/modules/vending/clothesmate.dm b/code/modules/vending/clothesmate.dm index 521c1e0999..2155d0fe8b 100644 --- a/code/modules/vending/clothesmate.dm +++ b/code/modules/vending/clothesmate.dm @@ -173,6 +173,12 @@ /obj/item/clothing/suit/jacket/letterman_nanotrasen = 5, /obj/item/clothing/suit/hooded/wintercoat/polychromic = 5) refill_canister = /obj/item/vending_refill/clothing + default_price = 60 + extra_price = 120 + payment_department = NO_FREEBIES + +/obj/machinery/vending/clothing/canLoadItem(obj/item/I,mob/user) + return (I.type in products) /obj/item/vending_refill/clothing machine_name = "ClothesMate" diff --git a/code/modules/vending/coffee.dm b/code/modules/vending/coffee.dm index 355d037f99..f4a8b2503e 100644 --- a/code/modules/vending/coffee.dm +++ b/code/modules/vending/coffee.dm @@ -14,6 +14,9 @@ /obj/item/reagent_containers/food/condiment/sugar = 1) refill_canister = /obj/item/vending_refill/coffee + default_price = 45 + extra_price = 150 + payment_department = ACCOUNT_SRV /obj/item/vending_refill/coffee machine_name = "Solar's Best Hot Drinks" diff --git a/code/modules/vending/cola.dm b/code/modules/vending/cola.dm index 57cf315209..5bbd0c3d02 100644 --- a/code/modules/vending/cola.dm +++ b/code/modules/vending/cola.dm @@ -21,6 +21,9 @@ /obj/item/reagent_containers/food/drinks/soda_cans/grey_bull = 1, /obj/item/reagent_containers/food/drinks/soda_cans/monkey_energy = 1) refill_canister = /obj/item/vending_refill/cola + default_price = 45 + extra_price = 200 + payment_department = ACCOUNT_SRV /obj/item/vending_refill/cola machine_name = "Robust Softdrinks" diff --git a/code/modules/vending/dinnerware.dm b/code/modules/vending/dinnerware.dm index da8baa7e1c..521e76b5e2 100644 --- a/code/modules/vending/dinnerware.dm +++ b/code/modules/vending/dinnerware.dm @@ -20,15 +20,17 @@ /obj/item/reagent_containers/food/condiment/saltshaker = 5, /obj/item/reagent_containers/food/condiment/peppermill = 5) contraband = list( - /obj/item/reagent_containers/food/snacks/cube/monkey= 1, /obj/item/kitchen/knife/butcher = 2, /obj/item/reagent_containers/syringe = 3) premium = list( - /obj/item/reagent_containers/food/condiment/enzyme = 1, - /obj/item/reagent_containers/glass/bottle/cryoxadone = 2) // Bartender can literally make this with upgraded parts, or it gets stolen from medical. + /obj/item/reagent_containers/food/condiment/enzyme = 1) armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) refill_canister = /obj/item/vending_refill/dinnerware resistance_flags = FIRE_PROOF + default_price = 50 + extra_price = 250 + payment_department = ACCOUNT_SRV + cost_multiplier_per_dept = list(ACCOUNT_SRV = 0) /obj/item/vending_refill/dinnerware - icon_state = "refill_cook" \ No newline at end of file + icon_state = "refill_cook" diff --git a/code/modules/vending/engineering.dm b/code/modules/vending/engineering.dm index e067c094f6..36bacd4259 100644 --- a/code/modules/vending/engineering.dm +++ b/code/modules/vending/engineering.dm @@ -4,7 +4,6 @@ desc = "Everything you need for do-it-yourself station repair." icon_state = "engi" icon_deny = "engi-deny" - req_access = list(ACCESS_ENGINE_EQUIP) products = list(/obj/item/clothing/under/rank/engineering/chief_engineer = 4, /obj/item/clothing/under/rank/engineering/engineer = 4, /obj/item/clothing/shoes/sneakers/orange = 4, @@ -29,3 +28,7 @@ /obj/item/stock_parts/manipulator = 5) armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF + default_price = 450 + extra_price = 500 + payment_department = ACCOUNT_ENG + cost_multiplier_per_dept = list(ACCOUNT_ENG = 0) diff --git a/code/modules/vending/engivend.dm b/code/modules/vending/engivend.dm index 15da7cab15..ca45483ff5 100644 --- a/code/modules/vending/engivend.dm +++ b/code/modules/vending/engivend.dm @@ -3,7 +3,6 @@ desc = "Spare tool vending. What? Did you expect some witty description?" icon_state = "engivend" icon_deny = "engivend-deny" - req_access = list(ACCESS_ENGINE_EQUIP) products = list(/obj/item/clothing/glasses/meson/engine = 5, /obj/item/clothing/glasses/welding = 5, /obj/item/multitool = 5, @@ -30,6 +29,10 @@ armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) refill_canister = /obj/item/vending_refill/engivend resistance_flags = FIRE_PROOF + default_price = 450 + extra_price = 500 + payment_department = ACCOUNT_ENG + cost_multiplier_per_dept = list(ACCOUNT_ENG = 0) /obj/item/vending_refill/engivend icon_state = "refill_engi" \ No newline at end of file diff --git a/code/modules/vending/games.dm b/code/modules/vending/games.dm index e663dca7ce..efd9aad673 100644 --- a/code/modules/vending/games.dm +++ b/code/modules/vending/games.dm @@ -11,6 +11,10 @@ premium = list(/obj/item/melee/skateboard/pro = 3, /obj/item/melee/skateboard/hoverboard = 1) refill_canister = /obj/item/vending_refill/games + default_price = 50 + extra_price = 250 + payment_department = ACCOUNT_SRV + cost_multiplier_per_dept = list(ACCOUNT_SRV = 0) /obj/item/vending_refill/games machine_name = "\improper Good Clean Fun" diff --git a/code/modules/vending/kinkmate.dm b/code/modules/vending/kinkmate.dm index acfeeddaa9..37f4e380ce 100644 --- a/code/modules/vending/kinkmate.dm +++ b/code/modules/vending/kinkmate.dm @@ -40,6 +40,9 @@ /obj/item/clothing/under/pants/chaps = 5 ) refill_canister = /obj/item/vending_refill/kink + default_price = 80 + extra_price = 250 + payment_department = NO_FREEBIES /obj/item/vending_refill/kink machine_name = "KinkMate" diff --git a/code/modules/vending/liberation.dm b/code/modules/vending/liberation.dm index affc1dfed7..c75d313c52 100644 --- a/code/modules/vending/liberation.dm +++ b/code/modules/vending/liberation.dm @@ -28,3 +28,6 @@ /obj/item/reagent_containers/food/snacks/burger/superbite = 3) //U S A armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF + default_price = 150 + extra_price = 500 + payment_department = ACCOUNT_SEC diff --git a/code/modules/vending/liberation_toy.dm b/code/modules/vending/liberation_toy.dm index e2c97b32db..8ed4cd85ae 100644 --- a/code/modules/vending/liberation_toy.dm +++ b/code/modules/vending/liberation_toy.dm @@ -25,3 +25,10 @@ armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF refill_canister = /obj/item/vending_refill/donksoft + default_price = 150 + extra_price = 300 + payment_department = NO_FREEBIES + +/obj/machinery/vending/toyliberationstation/Initialize() + . = ..() + cost_multiplier_per_dept = list("[ACCESS_SYNDICATE]" = 0) diff --git a/code/modules/vending/magivend.dm b/code/modules/vending/magivend.dm index ab7670c453..525b9f1af2 100644 --- a/code/modules/vending/magivend.dm +++ b/code/modules/vending/magivend.dm @@ -16,3 +16,6 @@ contraband = list(/obj/item/reagent_containers/glass/bottle/wizarditis = 1) //No one can get to the machine to hack it anyways; for the lulz - Microwave armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50, "magic" = 100) resistance_flags = FIRE_PROOF + default_price = 250 + extra_price = 500 + payment_department = ACCOUNT_SRV diff --git a/code/modules/vending/medical.dm b/code/modules/vending/medical.dm index d32af7de03..797fdabce7 100644 --- a/code/modules/vending/medical.dm +++ b/code/modules/vending/medical.dm @@ -4,7 +4,6 @@ icon_state = "med" icon_deny = "med-deny" product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?;Ping!" - req_access = list(ACCESS_MEDICAL) products = list(/obj/item/reagent_containers/syringe = 12, /obj/item/reagent_containers/dropper = 3, /obj/item/healthanalyzer = 4, @@ -47,6 +46,10 @@ armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF refill_canister = /obj/item/vending_refill/medical + default_price = 200 + extra_price = 250 + payment_department = ACCOUNT_MED + cost_multiplier_per_dept = list(ACCOUNT_MED = 0) /obj/item/vending_refill/medical machine_name = "NanoMed Plus" @@ -54,4 +57,8 @@ /obj/machinery/vending/medical/syndicate_access name = "\improper SyndiMed Plus" - req_access = list(ACCESS_SYNDICATE) + payment_department = NO_FREEBIES + +/obj/machinery/vending/medical/syndicate_access/Initialize() + . = ..() + cost_multiplier_per_dept = list("[ACCESS_SYNDICATE]" = 0) diff --git a/code/modules/vending/medical_wall.dm b/code/modules/vending/medical_wall.dm index a048d253c5..b51705c7e1 100644 --- a/code/modules/vending/medical_wall.dm +++ b/code/modules/vending/medical_wall.dm @@ -18,6 +18,10 @@ armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF refill_canister = /obj/item/vending_refill/wallmed + default_price = 0 + extra_price = 100 + payment_department = ACCOUNT_MED + cost_multiplier_per_dept = list(ACCOUNT_MED = 0) /obj/item/vending_refill/wallmed machine_name = "NanoMed" diff --git a/code/modules/vending/megaseed.dm b/code/modules/vending/megaseed.dm index 37ce00069c..df1e5eaba8 100644 --- a/code/modules/vending/megaseed.dm +++ b/code/modules/vending/megaseed.dm @@ -27,6 +27,7 @@ /obj/item/seeds/orange = 3, /obj/item/seeds/peach = 3, /obj/item/seeds/peanutseed = 3, + /obj/item/seeds/peas = 3, /obj/item/seeds/pineapple = 3, /obj/item/seeds/potato = 3, /obj/item/seeds/poppy = 3, @@ -57,6 +58,10 @@ armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) refill_canister = /obj/item/vending_refill/hydroseeds resistance_flags = FIRE_PROOF + default_price = 100 + extra_price = 350 + payment_department = ACCOUNT_SRV + cost_multiplier_per_dept = list(ACCOUNT_SRV = 0) /obj/item/vending_refill/hydroseeds icon_state = "refill_hydro" diff --git a/code/modules/vending/nutrimax.dm b/code/modules/vending/nutrimax.dm index 42b7848ac1..95ba4e23e8 100644 --- a/code/modules/vending/nutrimax.dm +++ b/code/modules/vending/nutrimax.dm @@ -19,6 +19,10 @@ armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) refill_canister = /obj/item/vending_refill/hydronutrients resistance_flags = FIRE_PROOF + default_price = 100 + extra_price = 250 + payment_department = ACCOUNT_SRV + cost_multiplier_per_dept = list(ACCOUNT_SRV = 0) /obj/item/vending_refill/hydronutrients icon_state = "refill_hydro" diff --git a/code/modules/vending/plasmaresearch.dm b/code/modules/vending/plasmaresearch.dm index 40b709f5b5..410154fa20 100644 --- a/code/modules/vending/plasmaresearch.dm +++ b/code/modules/vending/plasmaresearch.dm @@ -11,3 +11,7 @@ /obj/item/assembly/prox_sensor = 6, /obj/item/assembly/igniter = 6) contraband = list(/obj/item/assembly/health = 3) + default_price = 400 + extra_price = 600 + payment_department = ACCOUNT_SCI + cost_multiplier_per_dept = list(ACCOUNT_SCI = 0) diff --git a/code/modules/vending/robotics.dm b/code/modules/vending/robotics.dm index 852b7d65f0..3ad7134498 100644 --- a/code/modules/vending/robotics.dm +++ b/code/modules/vending/robotics.dm @@ -4,7 +4,6 @@ desc = "All the tools you need to create your own robot army." icon_state = "robotics" icon_deny = "robotics-deny" - req_access = list(ACCESS_ROBOTICS) products = list(/obj/item/clothing/suit/toggle/labcoat = 4, /obj/item/clothing/under/rank/rnd/roboticist = 4, /obj/item/stack/cable_coil = 4, @@ -21,3 +20,6 @@ /obj/item/crowbar = 5) armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF + default_price = 600 + payment_department = ACCOUNT_SCI + cost_multiplier_per_dept = list(ACCOUNT_SCI = 0) diff --git a/code/modules/vending/security.dm b/code/modules/vending/security.dm index b1a6297981..284e957864 100644 --- a/code/modules/vending/security.dm +++ b/code/modules/vending/security.dm @@ -4,7 +4,6 @@ product_ads = "Crack capitalist skulls!;Beat some heads in!;Don't forget - harm is good!;Your weapons are right here.;Handcuffs!;Freeze, scumbag!;Don't tase me bro!;Tase them, bro.;Why not have a donut?" icon_state = "sec" icon_deny = "sec-deny" - req_access = list(ACCESS_SECURITY) products = list(/obj/item/restraints/handcuffs = 8, /obj/item/restraints/handcuffs/cable/zipties = 10, /obj/item/grenade/flashbang = 4, @@ -26,6 +25,10 @@ armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF refill_canister = /obj/item/vending_refill/security + default_price = 650 + extra_price = 700 + payment_department = ACCOUNT_SEC + cost_multiplier_per_dept = list(ACCOUNT_SEC = 0) /obj/machinery/vending/security/pre_throw(obj/item/I) if(istype(I, /obj/item/grenade)) diff --git a/code/modules/vending/snack.dm b/code/modules/vending/snack.dm index 9dda649b24..e051d6135b 100644 --- a/code/modules/vending/snack.dm +++ b/code/modules/vending/snack.dm @@ -26,77 +26,16 @@ /obj/item/storage/box/donkpockets = 2) refill_canister = /obj/item/vending_refill/snack - var/chef_compartment_access = "28" //ACCESS_KITCHEN + canload_access_list = list(ACCESS_KITCHEN) + default_price = 60 + extra_price = 160 + payment_department = ACCOUNT_SRV + cost_multiplier_per_dept = list(ACCOUNT_SRV = 0) + input_display_header = "Chef's Food Selection" /obj/item/vending_refill/snack machine_name = "Getmore Chocolate Corp" -/obj/machinery/vending/snack/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/reagent_containers/food/snacks)) - if(!compartment_access_check(user)) - return - var/obj/item/reagent_containers/food/snacks/S = W - if(!S.junkiness) - if(!iscompartmentfull(user)) - if(!user.transferItemToLoc(W, src)) - return - food_load(W) - to_chat(user, "You insert [W] into [src]'s chef compartment.") - else - to_chat(user, "[src]'s chef compartment does not accept junk food.") - - else if(istype(W, /obj/item/storage/bag/tray)) - if(!compartment_access_check(user)) - return - var/obj/item/storage/T = W - var/loaded = 0 - var/denied_items = 0 - for(var/obj/item/reagent_containers/food/snacks/S in T.contents) - if(iscompartmentfull(user)) - break - if(!S.junkiness) - SEND_SIGNAL(T, COMSIG_TRY_STORAGE_TAKE, S, src, TRUE) - food_load(S) - loaded++ - else - denied_items++ - if(denied_items) - to_chat(user, "[src] refuses some items.") - if(loaded) - to_chat(user, "You insert [loaded] dishes into [src]'s chef compartment.") - updateUsrDialog() - return - - else - return ..() - -/obj/machinery/vending/snack/Destroy() - for(var/obj/item/reagent_containers/food/snacks/S in contents) - S.forceMove(get_turf(src)) - return ..() - -/obj/machinery/vending/snack/proc/compartment_access_check(user) - req_access_txt = chef_compartment_access - if(!allowed(user) && !(obj_flags & EMAGGED) && scan_id) - to_chat(user, "[src]'s chef compartment blinks red: Access denied.") - req_access_txt = "0" - return 0 - req_access_txt = "0" - return 1 - -/obj/machinery/vending/snack/proc/iscompartmentfull(mob/user) - if(contents.len >= 30) // no more than 30 dishes can fit inside - to_chat(user, "[src]'s chef compartment is full.") - return 1 - return 0 - -/obj/machinery/vending/snack/proc/food_load(obj/item/reagent_containers/food/snacks/S) - if(dish_quants[S.name]) - dish_quants[S.name]++ - else - dish_quants[S.name] = 1 - sortList(dish_quants) - /obj/machinery/vending/snack/random name = "\improper Random Snackies" icon_state = "random_snack" diff --git a/code/modules/vending/sovietsoda.dm b/code/modules/vending/sovietsoda.dm index 39364d78da..d820794660 100644 --- a/code/modules/vending/sovietsoda.dm +++ b/code/modules/vending/sovietsoda.dm @@ -7,3 +7,6 @@ contraband = list(/obj/item/reagent_containers/food/drinks/drinkingglass/filled/cola = 20) armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF + default_price = 1 + extra_price = 1 + payment_department = NO_FREEBIES diff --git a/code/modules/vending/sovietvend.dm b/code/modules/vending/sovietvend.dm index c555362fb6..daf64d5f3e 100644 --- a/code/modules/vending/sovietvend.dm +++ b/code/modules/vending/sovietvend.dm @@ -23,6 +23,9 @@ premium = list() refill_canister = /obj/item/vending_refill/soviet + default_price = 1 + extra_price = 1 + payment_department = NO_FREEBIES /obj/item/vending_refill/soviet machine_name = "sovietvend" diff --git a/code/modules/vending/sustenance.dm b/code/modules/vending/sustenance.dm index 9783607a21..55e6b02e8e 100644 --- a/code/modules/vending/sustenance.dm +++ b/code/modules/vending/sustenance.dm @@ -14,6 +14,9 @@ armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) refill_canister = /obj/item/vending_refill/sustenance resistance_flags = FIRE_PROOF + default_price = 0 + extra_price = 0 + payment_department = NO_FREEBIES /obj/item/vending_refill/sustenance icon_state = "refill_cook" diff --git a/code/modules/vending/toys.dm b/code/modules/vending/toys.dm index 08bb4615bb..a00dd17a9c 100644 --- a/code/modules/vending/toys.dm +++ b/code/modules/vending/toys.dm @@ -25,6 +25,9 @@ armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF refill_canister = /obj/item/vending_refill/donksoft + default_price = 150 + extra_price = 300 + payment_department = ACCOUNT_SRV /obj/item/vending_refill/donksoft machine_name = "Donksoft Toy Vendor" diff --git a/code/modules/vending/wardrobes.dm b/code/modules/vending/wardrobes.dm index acd58959f1..41fa9a99f8 100644 --- a/code/modules/vending/wardrobes.dm +++ b/code/modules/vending/wardrobes.dm @@ -1,6 +1,15 @@ /obj/item/vending_refill/wardrobe icon_state = "refill_clothes" +/obj/machinery/vending/wardrobe + default_price = 350 + extra_price = 400 + payment_department = NO_FREEBIES + input_display_header = "Returned Clothing" + +/obj/machinery/vending/wardrobe/canLoadItem(obj/item/I,mob/user) + return (I.type in products) + /obj/machinery/vending/wardrobe/sec_wardrobe name = "\improper SecDrobe" desc = "A vending machine for security and security-related clothing!" @@ -22,6 +31,8 @@ premium = list(/obj/item/clothing/under/rank/security/officer/formal = 5, /obj/item/clothing/head/beret/sec/navyofficer = 5) refill_canister = /obj/item/vending_refill/wardrobe/sec_wardrobe + payment_department = ACCOUNT_SEC + cost_multiplier_per_dept = list(ACCOUNT_SEC = 0) /obj/item/vending_refill/wardrobe/sec_wardrobe machine_name = "SecDrobe" @@ -38,6 +49,7 @@ /obj/item/storage/backpack/medic = 5, /obj/item/storage/backpack/satchel/med = 5, /obj/item/clothing/suit/hooded/wintercoat/medical = 5, + /obj/item/clothing/suit/hooded/wintercoat/paramedic = 2, /obj/item/clothing/under/rank/medical/doctor/nurse = 5, /obj/item/clothing/head/nursehat = 5, /obj/item/clothing/under/rank/medical/doctor/skirt= 5, @@ -57,6 +69,8 @@ /obj/item/clothing/suit/apron/surgical = 5, /obj/item/clothing/mask/surgical = 5) refill_canister = /obj/item/vending_refill/wardrobe/medi_wardrobe + payment_department = ACCOUNT_MED + cost_multiplier_per_dept = list(ACCOUNT_MED = 0) /obj/item/vending_refill/wardrobe/medi_wardrobe machine_name = "MediDrobe" @@ -80,6 +94,8 @@ /obj/item/clothing/head/hardhat = 5, /obj/item/clothing/head/hardhat/weldhat = 3) refill_canister = /obj/item/vending_refill/wardrobe/engi_wardrobe + payment_department = ACCOUNT_ENG + cost_multiplier_per_dept = list(ACCOUNT_ENG = 0) /obj/item/vending_refill/wardrobe/engi_wardrobe machine_name = "EngiDrobe" @@ -101,6 +117,8 @@ /obj/item/clothing/under/rank/engineering/atmospheric_technician/skirt = 5, /obj/item/clothing/shoes/sneakers/black = 5) refill_canister = /obj/item/vending_refill/wardrobe/atmos_wardrobe + payment_department = ACCOUNT_ENG + cost_multiplier_per_dept = list(ACCOUNT_ENG = 0) /obj/item/vending_refill/wardrobe/atmos_wardrobe machine_name = "AtmosDrobe" @@ -119,6 +137,8 @@ /obj/item/clothing/head/soft = 5, /obj/item/radio/headset/headset_cargo = 3) refill_canister = /obj/item/vending_refill/wardrobe/cargo_wardrobe + payment_department = ACCOUNT_CAR + cost_multiplier_per_dept = list(ACCOUNT_CAR = 0) /obj/item/vending_refill/wardrobe/cargo_wardrobe machine_name = "CargoDrobe" @@ -141,6 +161,8 @@ /obj/item/clothing/mask/bandana/skull = 2) contraband = list(/obj/item/clothing/suit/hooded/techpriest = 2) refill_canister = /obj/item/vending_refill/wardrobe/robo_wardrobe + payment_department = ACCOUNT_SCI + cost_multiplier_per_dept = list(ACCOUNT_SCI = 0) /obj/item/vending_refill/wardrobe/robo_wardrobe machine_name = "RoboDrobe" @@ -163,6 +185,8 @@ /obj/item/radio/headset/headset_sci = 4, /obj/item/clothing/mask/gas = 5) refill_canister = /obj/item/vending_refill/wardrobe/science_wardrobe + payment_department = ACCOUNT_SCI + cost_multiplier_per_dept = list(ACCOUNT_SCI = 0) /obj/item/vending_refill/wardrobe/science_wardrobe machine_name = "SciDrobe" @@ -182,6 +206,8 @@ /obj/item/clothing/under/rank/civilian/hydroponics/skirt = 5, /obj/item/clothing/mask/bandana = 4) refill_canister = /obj/item/vending_refill/wardrobe/hydro_wardrobe + payment_department = ACCOUNT_SRV + cost_multiplier_per_dept = list(ACCOUNT_SRV = 0) /obj/item/vending_refill/wardrobe/hydro_wardrobe machine_name = "HyDrobe" @@ -206,6 +232,8 @@ /obj/item/clothing/glasses/regular/jamjar = 1, /obj/item/storage/bag/books = 1) refill_canister = /obj/item/vending_refill/wardrobe/curator_wardrobe + payment_department = ACCOUNT_CIV + cost_multiplier_per_dept = list(ACCOUNT_CIV = 0) /obj/item/vending_refill/wardrobe/curator_wardrobe machine_name = "CuraDrobe" @@ -234,6 +262,8 @@ /obj/item/clothing/neck/petcollar = 3, /obj/item/storage/belt/bandolier = 1) refill_canister = /obj/item/vending_refill/wardrobe/bar_wardrobe + payment_department = ACCOUNT_SRV + cost_multiplier_per_dept = list(ACCOUNT_SRV = 0) /obj/item/vending_refill/wardrobe/bar_wardrobe machine_name = "BarDrobe" @@ -259,6 +289,8 @@ /obj/item/book/granter/crafting_recipe/cooking_sweets_101 = 2, /obj/item/book/granter/crafting_recipe/coldcooking = 2) refill_canister = /obj/item/vending_refill/wardrobe/chef_wardrobe + payment_department = ACCOUNT_SRV + cost_multiplier_per_dept = list(ACCOUNT_SRV = 0) /obj/item/vending_refill/wardrobe/chef_wardrobe machine_name = "ChefDrobe" @@ -290,6 +322,8 @@ /obj/item/screwdriver = 2, /obj/item/stack/cable_coil/random = 4) refill_canister = /obj/item/vending_refill/wardrobe/jani_wardrobe + payment_department = ACCOUNT_SRV + cost_multiplier_per_dept = list(ACCOUNT_SRV = 0) /obj/item/vending_refill/wardrobe/jani_wardrobe machine_name = "JaniDrobe" @@ -321,6 +355,8 @@ /obj/item/clothing/shoes/laceup = 3, /obj/item/clothing/accessory/lawyers_badge = 3) refill_canister = /obj/item/vending_refill/wardrobe/law_wardrobe + payment_department = ACCOUNT_CIV + cost_multiplier_per_dept = list(ACCOUNT_CIV = 0) /obj/item/vending_refill/wardrobe/law_wardrobe machine_name = "LawDrobe" @@ -347,6 +383,8 @@ premium = list(/obj/item/toy/plush/plushvar = 1, /obj/item/toy/plush/narplush = 1) refill_canister = /obj/item/vending_refill/wardrobe/chap_wardrobe + payment_department = ACCOUNT_CIV + cost_multiplier_per_dept = list(ACCOUNT_CIV = 0) /obj/item/vending_refill/wardrobe/chap_wardrobe machine_name = "ChapDrobe" @@ -368,6 +406,8 @@ /obj/item/storage/bag/chemistry = 3, /obj/item/fermichem/pHbooklet = 3)//pH indicator) refill_canister = /obj/item/vending_refill/wardrobe/chem_wardrobe + payment_department = ACCOUNT_MED + cost_multiplier_per_dept = list(ACCOUNT_MED = 0) /obj/item/vending_refill/wardrobe/chem_wardrobe machine_name = "ChemDrobe" @@ -386,6 +426,8 @@ /obj/item/storage/backpack/genetics = 3, /obj/item/storage/backpack/satchel/gen = 3) refill_canister = /obj/item/vending_refill/wardrobe/gene_wardrobe + payment_department = ACCOUNT_MED + cost_multiplier_per_dept = list(ACCOUNT_MED = 0) /obj/item/vending_refill/wardrobe/gene_wardrobe machine_name = "GeneDrobe" @@ -406,6 +448,8 @@ /obj/item/storage/backpack/virology = 3, /obj/item/storage/backpack/satchel/vir = 3) refill_canister = /obj/item/vending_refill/wardrobe/viro_wardrobe + payment_department = ACCOUNT_MED + cost_multiplier_per_dept = list(ACCOUNT_MED = 0) /obj/item/vending_refill/wardrobe/viro_wardrobe machine_name = "ViroDrobe" @@ -416,7 +460,6 @@ icon_state = "capsdrobe" icon_deny = "capsdrobe-deny" product_ads = "Only the greatest for a commander such as ours." - req_access = list(ACCESS_CAPTAIN) vend_reply = "A wonderful day to you, great leader." products = list(/obj/item/clothing/suit/hooded/wintercoat/captain = 1, /obj/item/storage/backpack/captain = 1, @@ -436,6 +479,11 @@ /obj/item/clothing/glasses/sunglasses/gar/supergar = 1, /obj/item/clothing/gloves/color/captain = 1) refill_canister = /obj/item/vending_refill/wardrobe/cap_wardrobe + payment_department = ACCOUNT_CIV + +/obj/machinery/vending/wardrobe/cap_wardrobe/Initialize() + . = ..() + cost_multiplier_per_dept = list("[ACCESS_CAPTAIN]" = 0) /obj/item/vending_refill/wardrobe/cap_wardrobe machine_name = "Captain's Wardrobe" diff --git a/code/modules/vending/youtool.dm b/code/modules/vending/youtool.dm index c027cea6e5..6b38ec0b9d 100644 --- a/code/modules/vending/youtool.dm +++ b/code/modules/vending/youtool.dm @@ -15,12 +15,17 @@ /obj/item/flashlight/glowstick/red = 6, /obj/item/flashlight = 7) contraband = list(/obj/item/weldingtool/largetank = 4, - /obj/item/clothing/gloves/color/fyellow = 4) + /obj/item/clothing/gloves/color/fyellow = 4, + /obj/item/multitool = 2) premium = list(/obj/item/clothing/gloves/color/yellow = 2, /obj/item/weldingtool/hugetank = 2) armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70) refill_canister = /obj/item/vending_refill/tool resistance_flags = FIRE_PROOF + default_price = 50 + extra_price = 300 + payment_department = ACCOUNT_ENG + cost_multiplier_per_dept = list(ACCOUNT_ENG = 0) /obj/item/vending_refill/tool icon_state = "refill_engi" \ No newline at end of file diff --git a/code/modules/vore/eating/belly_obj.dm b/code/modules/vore/eating/belly_obj.dm index b188cc0a99..03d0bbba45 100644 --- a/code/modules/vore/eating/belly_obj.dm +++ b/code/modules/vore/eating/belly_obj.dm @@ -512,7 +512,7 @@ if(!digested) items_preserved |= item else -// owner.nutrition += (5 * digested) // haha no. +// owner.adjust_nutrition(5 * digested) // haha no. if(iscyborg(owner)) var/mob/living/silicon/robot/R = owner R.cell.charge += (50 * digested) @@ -542,7 +542,7 @@ if (!(R in contents)) return // User is not in this belly - R.setClickCooldown(50) + R.changeNext_move(CLICK_CD_BREAKOUT*0.5) if(owner.stat) //If owner is stat (dead, KO) we can actually escape to_chat(R,"You attempt to climb out of \the [lowertext(name)]. (This will take around [escapetime/10] seconds.)") diff --git a/code/modules/vore/eating/bellymodes.dm b/code/modules/vore/eating/bellymodes.dm index 2caaae401e..77864021b4 100644 --- a/code/modules/vore/eating/bellymodes.dm +++ b/code/modules/vore/eating/bellymodes.dm @@ -98,7 +98,7 @@ to_chat(M, "[digest_alert_prey]") M.visible_message("You watch as [owner]'s form loses its additions.") - owner.nutrition += 400 // so eating dead mobs gives you *something*. + owner.adjust_nutrition(400) // so eating dead mobs gives you *something*. play_sound = pick(pred_death) if(M && M.client && M.client.prefs.cit_toggles & DIGESTION_NOISES) SEND_SOUND(M,prey_death) @@ -112,7 +112,7 @@ // Deal digestion damage (and feed the pred) if(!(M.status_flags & GODMODE)) M.adjustFireLoss(digest_burn) - owner.nutrition += 1 + owner.adjust_nutrition(1) //Contaminate or gurgle items var/obj/item/T = pick(touchable_items) @@ -130,7 +130,7 @@ if(owner.nutrition >= NUTRITION_LEVEL_STARVING && (M.health < M.maxHealth)) M.adjustBruteLoss(-3) M.adjustFireLoss(-3) - owner.nutrition -= 5 + owner.adjust_nutrition(-5) //for when you just want people to squelch around if(DM_NOISY) @@ -155,8 +155,8 @@ if(M.nutrition >= 100) //Drain them until there's no nutrients left. Slowly "absorb" them. var/oldnutrition = (M.nutrition * 0.05) - M.nutrition = (M.nutrition * 0.95) - owner.nutrition += oldnutrition + M.set_nutrition(M.nutrition * 0.95) + owner.adjust_nutrition(oldnutrition) else if(M.nutrition < 100) //When they're finally drained. absorb_living(M) to_update = TRUE @@ -168,7 +168,7 @@ DISABLE_BITFIELD(M.vore_flags, ABSORBED) to_chat(M,"You suddenly feel solid again ") to_chat(owner,"You feel like a part of you is missing.") - owner.nutrition -= 100 + owner.adjust_nutrition(-100) to_update = TRUE //because dragons need snowflake guts diff --git a/code/modules/vore/eating/living.dm b/code/modules/vore/eating/living.dm index 33f8d78300..a7cc316cc3 100644 --- a/code/modules/vore/eating/living.dm +++ b/code/modules/vore/eating/living.dm @@ -358,6 +358,9 @@ if(incapacitated(ignore_restraints = TRUE)) to_chat(src, "You can't do that while incapacitated.") return + if(next_move > world.time) + to_chat(src, "You can't do that so fast, slow down.") + return var/list/choices for(var/mob/living/L in view(1)) @@ -372,7 +375,7 @@ if(QDELETED(tasted) || (tasted.ckey && !(tasted.client?.prefs.vore_flags & LICKABLE)) || !Adjacent(tasted) || incapacitated(ignore_restraints = TRUE)) return - setClickCooldown(100) + changeNext_move(CLICK_CD_MELEE) visible_message("[src] licks [tasted]!","You lick [tasted]. They taste rather like [tasted.get_taste_message()].","Slurp!") diff --git a/code/modules/zombie/items.dm b/code/modules/zombie/items.dm index 0f6ef14cd1..d4d92f54c4 100644 --- a/code/modules/zombie/items.dm +++ b/code/modules/zombie/items.dm @@ -74,4 +74,4 @@ user.adjustCloneLoss(-hp_gained, 0) user.updatehealth() user.adjustOrganLoss(ORGAN_SLOT_BRAIN, -hp_gained) // Zom Bee gibbers "BRAAAAISNSs!1!" - user.nutrition = min(user.nutrition + hp_gained, NUTRITION_LEVEL_FULL) + user.adjust_nutrition(hp_gained, NUTRITION_LEVEL_FULL) diff --git a/config/game_options.txt b/config/game_options.txt index 4751e96d18..f65c1bfff5 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -139,6 +139,20 @@ MIDROUND_ANTAG CHANGELING MIDROUND_ANTAG WIZARD #MIDROUND_ANTAG MONKEY +## Toggles for whether this mode should force antags even if not enough players have it enabled. +## If it's off, it just won't roll as many antags. +#FORCE_ANTAG_COUNT TRAITOR +#FORCE_ANTAG_COUNT TRAITORBRO +#FORCE_ANTAG_COUNT TRAITORCHAN +#FORCE_ANTAG_COUNT INTERNAL_AFFAIRS +FORCE_ANTAG_COUNT NUCLEAR +FORCE_ANTAG_COUNT REVOLUTION +FORCE_ANTAG_COUNT CULT +FORCE_ANTAG_COUNT CLOCKWORK_CULT +#FORCE_ANTAG_COUNT CHANGELING +#FORCE_ANTAG_COUNT WIZARD +#FORCE_ANTAG_COUNT MONKEY + ## Uncomment these for overrides of the minimum / maximum number of players in a round type. ## If you set any of these occasionally check to see if you still need them as the modes ## will still be actively rebalanced around the SUGGESTED populations, not your overrides. @@ -589,6 +603,9 @@ NIGHTSHIFT_TOGGLE_PUBLIC_REQUIRES_AUTH ## A cap on how many monkeys may be created via monkey cubes MONKEYCAP 64 +## Enable the capitalist agenda on your server. +ECONOMY + ## Uncomment to use TG-style combat #DISABLE_STAMBUFFER @@ -641,4 +658,8 @@ THRESHOLD_BODY_SIZE_SLOWDOWN 0.85 BODY_SIZE_SLOWDOWN_MULTIPLIER 0.25 ## Allows players to set a hexadecimal color of their choice as skin tone, on top of the standard ones. -ALLOW_CUSTOM_SKINTONES \ No newline at end of file +ALLOW_CUSTOM_SKINTONES + +## Enables the FoV component, which hides objects and mobs behind the parent from their sight, unless they turn around, duh. +## Camera mobs, AIs, ghosts and some other are of course exempt from this. This also doesn't influence simplemob AI, for the best. +#USE_FIELD_OF_VISION \ No newline at end of file diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi index 0731583733..0c4784553c 100644 Binary files a/icons/effects/beam.dmi and b/icons/effects/beam.dmi differ diff --git a/icons/misc/field_of_vision.dmi b/icons/misc/field_of_vision.dmi new file mode 100644 index 0000000000..015cecd88c Binary files /dev/null and b/icons/misc/field_of_vision.dmi differ diff --git a/icons/misc/language.dmi b/icons/misc/language.dmi index 3b4ac1a16a..155dbab98d 100644 Binary files a/icons/misc/language.dmi and b/icons/misc/language.dmi differ diff --git a/icons/mob/clothing/back.dmi b/icons/mob/clothing/back.dmi index 66a47d21f2..d307b5b6c9 100644 Binary files a/icons/mob/clothing/back.dmi and b/icons/mob/clothing/back.dmi differ diff --git a/icons/mob/clothing/feet.dmi b/icons/mob/clothing/feet.dmi index a0dfe6e482..2b28d06976 100644 Binary files a/icons/mob/clothing/feet.dmi and b/icons/mob/clothing/feet.dmi differ diff --git a/icons/mob/clothing/feet_digi.dmi b/icons/mob/clothing/feet_digi.dmi index 626c67a71c..7815f3d0a4 100644 Binary files a/icons/mob/clothing/feet_digi.dmi and b/icons/mob/clothing/feet_digi.dmi differ diff --git a/icons/mob/clothing/hands.dmi b/icons/mob/clothing/hands.dmi index 3860fa4b7e..856fe2149a 100644 Binary files a/icons/mob/clothing/hands.dmi and b/icons/mob/clothing/hands.dmi differ diff --git a/icons/mob/clothing/head.dmi b/icons/mob/clothing/head.dmi index 3c5dfe5012..3613488027 100644 Binary files a/icons/mob/clothing/head.dmi and b/icons/mob/clothing/head.dmi differ diff --git a/icons/mob/clothing/mask.dmi b/icons/mob/clothing/mask.dmi index ee36c59209..13f288677f 100644 Binary files a/icons/mob/clothing/mask.dmi and b/icons/mob/clothing/mask.dmi differ diff --git a/icons/mob/clothing/mask_muzzled.dmi b/icons/mob/clothing/mask_muzzled.dmi index ed74796c03..0a10f1edbe 100644 Binary files a/icons/mob/clothing/mask_muzzled.dmi and b/icons/mob/clothing/mask_muzzled.dmi differ diff --git a/icons/mob/clothing/neck.dmi b/icons/mob/clothing/neck.dmi index 78073222ca..86dec62a41 100644 Binary files a/icons/mob/clothing/neck.dmi and b/icons/mob/clothing/neck.dmi differ diff --git a/icons/mob/clothing/suit.dmi b/icons/mob/clothing/suit.dmi index 803b4aa390..134c03f71b 100644 Binary files a/icons/mob/clothing/suit.dmi and b/icons/mob/clothing/suit.dmi differ diff --git a/icons/mob/clothing/uniform.dmi b/icons/mob/clothing/uniform.dmi index b717b33c61..e126629b77 100644 Binary files a/icons/mob/clothing/uniform.dmi and b/icons/mob/clothing/uniform.dmi differ diff --git a/icons/mob/dogborg.dmi b/icons/mob/dogborg.dmi deleted file mode 100644 index 856724be1f..0000000000 Binary files a/icons/mob/dogborg.dmi and /dev/null differ diff --git a/icons/mob/inhands/equipment/security_lefthand.dmi b/icons/mob/inhands/equipment/security_lefthand.dmi index 01f8e2ca27..47447f80d0 100644 Binary files a/icons/mob/inhands/equipment/security_lefthand.dmi and b/icons/mob/inhands/equipment/security_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/security_righthand.dmi b/icons/mob/inhands/equipment/security_righthand.dmi index d2126fe22f..79aab1c5cd 100644 Binary files a/icons/mob/inhands/equipment/security_righthand.dmi and b/icons/mob/inhands/equipment/security_righthand.dmi differ diff --git a/icons/mob/inhands/equipment/shields_lefthand.dmi b/icons/mob/inhands/equipment/shields_lefthand.dmi index 24bb824f1d..850bbaa043 100644 Binary files a/icons/mob/inhands/equipment/shields_lefthand.dmi and b/icons/mob/inhands/equipment/shields_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/shields_righthand.dmi b/icons/mob/inhands/equipment/shields_righthand.dmi index 31d84f480c..d4db35b9b2 100644 Binary files a/icons/mob/inhands/equipment/shields_righthand.dmi and b/icons/mob/inhands/equipment/shields_righthand.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index 1cd090a3e9..19738ed490 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index 24c9a2d777..9589e338e1 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/mob/robot_items.dmi b/icons/mob/robot_items.dmi index 862e1be384..06521f1a84 100644 Binary files a/icons/mob/robot_items.dmi and b/icons/mob/robot_items.dmi differ diff --git a/icons/mob/talk.dmi b/icons/mob/talk.dmi index 05fe6f5623..0a56321037 100644 Binary files a/icons/mob/talk.dmi and b/icons/mob/talk.dmi differ diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi index a26b01883e..e0b02d2adc 100644 Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ diff --git a/icons/obj/artstuff.dmi b/icons/obj/artstuff.dmi index ea24341f5e..14970b76ef 100644 Binary files a/icons/obj/artstuff.dmi and b/icons/obj/artstuff.dmi differ diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi index 1169888b34..4f2238e391 100644 Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ diff --git a/icons/obj/chess.dmi b/icons/obj/chess.dmi index 191eed8843..09d9c766fd 100644 Binary files a/icons/obj/chess.dmi and b/icons/obj/chess.dmi differ diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi index 2a6ce77f38..535ae0d241 100644 Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index c88d1ce766..1768d8a1c6 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi index 0590104c30..6bae5154ac 100644 Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index 607c26bb62..fcfbd36df6 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/crates.dmi b/icons/obj/crates.dmi index ecb66d0119..532324fcf4 100644 Binary files a/icons/obj/crates.dmi and b/icons/obj/crates.dmi differ diff --git a/icons/obj/decals.dmi b/icons/obj/decals.dmi index 7ed9244ea4..f66767292c 100644 Binary files a/icons/obj/decals.dmi and b/icons/obj/decals.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 58c1cd921c..f2a8328717 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/doors/shutters.dmi b/icons/obj/doors/shutters.dmi index 6f10860cfa..816d1f94f9 100644 Binary files a/icons/obj/doors/shutters.dmi and b/icons/obj/doors/shutters.dmi differ diff --git a/icons/obj/doors/shutters_radiation.dmi b/icons/obj/doors/shutters_radiation.dmi index 36d232b197..657b613b0c 100644 Binary files a/icons/obj/doors/shutters_radiation.dmi and b/icons/obj/doors/shutters_radiation.dmi differ diff --git a/icons/obj/doors/shutters_window.dmi b/icons/obj/doors/shutters_window.dmi index 20197593c1..c99790c6cf 100644 Binary files a/icons/obj/doors/shutters_window.dmi and b/icons/obj/doors/shutters_window.dmi differ diff --git a/icons/obj/economy.dmi b/icons/obj/economy.dmi index 9cc6498454..a73f50ef7f 100644 Binary files a/icons/obj/economy.dmi and b/icons/obj/economy.dmi differ diff --git a/icons/obj/food/burgerbread.dmi b/icons/obj/food/burgerbread.dmi index 5ee3db49e9..414930ac25 100644 Binary files a/icons/obj/food/burgerbread.dmi and b/icons/obj/food/burgerbread.dmi differ diff --git a/icons/obj/food/food.dmi b/icons/obj/food/food.dmi index f5e2dc5692..9affc07f88 100644 Binary files a/icons/obj/food/food.dmi and b/icons/obj/food/food.dmi differ diff --git a/modular_citadel/icons/obj/genitals/breasts.dmi b/icons/obj/genitals/breasts.dmi similarity index 100% rename from modular_citadel/icons/obj/genitals/breasts.dmi rename to icons/obj/genitals/breasts.dmi diff --git a/modular_citadel/icons/obj/genitals/breasts_onmob.dmi b/icons/obj/genitals/breasts_onmob.dmi similarity index 100% rename from modular_citadel/icons/obj/genitals/breasts_onmob.dmi rename to icons/obj/genitals/breasts_onmob.dmi diff --git a/modular_citadel/icons/obj/genitals/dildo.dmi b/icons/obj/genitals/dildo.dmi similarity index 100% rename from modular_citadel/icons/obj/genitals/dildo.dmi rename to icons/obj/genitals/dildo.dmi diff --git a/modular_citadel/icons/obj/genitals/effects.dmi b/icons/obj/genitals/effects.dmi similarity index 100% rename from modular_citadel/icons/obj/genitals/effects.dmi rename to icons/obj/genitals/effects.dmi diff --git a/modular_citadel/icons/obj/genitals/hud.dmi b/icons/obj/genitals/hud.dmi similarity index 100% rename from modular_citadel/icons/obj/genitals/hud.dmi rename to icons/obj/genitals/hud.dmi diff --git a/modular_citadel/icons/obj/genitals/onahole.dmi b/icons/obj/genitals/onahole.dmi similarity index 100% rename from modular_citadel/icons/obj/genitals/onahole.dmi rename to icons/obj/genitals/onahole.dmi diff --git a/modular_citadel/icons/obj/genitals/penis.dmi b/icons/obj/genitals/penis.dmi similarity index 100% rename from modular_citadel/icons/obj/genitals/penis.dmi rename to icons/obj/genitals/penis.dmi diff --git a/modular_citadel/icons/obj/genitals/penis_onmob.dmi b/icons/obj/genitals/penis_onmob.dmi similarity index 100% rename from modular_citadel/icons/obj/genitals/penis_onmob.dmi rename to icons/obj/genitals/penis_onmob.dmi diff --git a/modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi b/icons/obj/genitals/taur_penis_onmob.dmi similarity index 100% rename from modular_citadel/icons/obj/genitals/taur_penis_onmob.dmi rename to icons/obj/genitals/taur_penis_onmob.dmi diff --git a/modular_citadel/icons/obj/genitals/testicles.dmi b/icons/obj/genitals/testicles.dmi similarity index 100% rename from modular_citadel/icons/obj/genitals/testicles.dmi rename to icons/obj/genitals/testicles.dmi diff --git a/modular_citadel/icons/obj/genitals/testicles_onmob.dmi b/icons/obj/genitals/testicles_onmob.dmi similarity index 100% rename from modular_citadel/icons/obj/genitals/testicles_onmob.dmi rename to icons/obj/genitals/testicles_onmob.dmi diff --git a/modular_citadel/icons/obj/genitals/vagina.dmi b/icons/obj/genitals/vagina.dmi similarity index 100% rename from modular_citadel/icons/obj/genitals/vagina.dmi rename to icons/obj/genitals/vagina.dmi diff --git a/modular_citadel/icons/obj/genitals/vagina_onmob.dmi b/icons/obj/genitals/vagina_onmob.dmi similarity index 100% rename from modular_citadel/icons/obj/genitals/vagina_onmob.dmi rename to icons/obj/genitals/vagina_onmob.dmi diff --git a/icons/obj/hydroponics/growing_vegetables.dmi b/icons/obj/hydroponics/growing_vegetables.dmi index 63cf069186..b426b8f6de 100644 Binary files a/icons/obj/hydroponics/growing_vegetables.dmi and b/icons/obj/hydroponics/growing_vegetables.dmi differ diff --git a/icons/obj/hydroponics/harvest.dmi b/icons/obj/hydroponics/harvest.dmi index c7c31581f3..fd9d310c73 100644 Binary files a/icons/obj/hydroponics/harvest.dmi and b/icons/obj/hydroponics/harvest.dmi differ diff --git a/icons/obj/hydroponics/seeds.dmi b/icons/obj/hydroponics/seeds.dmi index 62843e3f54..15b7e2b96c 100644 Binary files a/icons/obj/hydroponics/seeds.dmi and b/icons/obj/hydroponics/seeds.dmi differ diff --git a/icons/obj/improvised.dmi b/icons/obj/improvised.dmi index b90e3cb3bb..5c2c2a1f1b 100644 Binary files a/icons/obj/improvised.dmi and b/icons/obj/improvised.dmi differ diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi index eee164cead..c95e6e5cb7 100644 Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ diff --git a/icons/obj/machines/bepis.dmi b/icons/obj/machines/bepis.dmi new file mode 100644 index 0000000000..f348c2e1b0 Binary files /dev/null and b/icons/obj/machines/bepis.dmi differ diff --git a/icons/obj/mauna_mug.dmi b/icons/obj/mauna_mug.dmi new file mode 100644 index 0000000000..fd576072fd Binary files /dev/null and b/icons/obj/mauna_mug.dmi differ diff --git a/icons/obj/money_machine.dmi b/icons/obj/money_machine.dmi new file mode 100644 index 0000000000..3e7fde761f Binary files /dev/null and b/icons/obj/money_machine.dmi differ diff --git a/icons/obj/money_machine_64.dmi b/icons/obj/money_machine_64.dmi new file mode 100644 index 0000000000..7bad748f2e Binary files /dev/null and b/icons/obj/money_machine_64.dmi differ diff --git a/icons/obj/monitors.dmi b/icons/obj/monitors.dmi index 5e91660e87..580d78900d 100644 Binary files a/icons/obj/monitors.dmi and b/icons/obj/monitors.dmi differ diff --git a/icons/obj/objects.dmi b/icons/obj/objects.dmi index c8927edde4..03b7a9e44f 100644 Binary files a/icons/obj/objects.dmi and b/icons/obj/objects.dmi differ diff --git a/icons/obj/reagentfillings.dmi b/icons/obj/reagentfillings.dmi index 3d5a825f27..f07928741d 100644 Binary files a/icons/obj/reagentfillings.dmi and b/icons/obj/reagentfillings.dmi differ diff --git a/icons/obj/shields.dmi b/icons/obj/shields.dmi index ed528d4a5a..c8b1110e1a 100644 Binary files a/icons/obj/shields.dmi and b/icons/obj/shields.dmi differ diff --git a/icons/obj/smooth_structures/rollingtable.dmi b/icons/obj/smooth_structures/rollingtable.dmi new file mode 100644 index 0000000000..9e559a75d9 Binary files /dev/null and b/icons/obj/smooth_structures/rollingtable.dmi differ diff --git a/icons/obj/stack_objects.dmi b/icons/obj/stack_objects.dmi index 5b0c05d43d..d327dc8988 100644 Binary files a/icons/obj/stack_objects.dmi and b/icons/obj/stack_objects.dmi differ diff --git a/icons/obj/tools.dmi b/icons/obj/tools.dmi index 6a2bb343df..0ff7d4a607 100644 Binary files a/icons/obj/tools.dmi and b/icons/obj/tools.dmi differ diff --git a/icons/obj/vending_restock.dmi b/icons/obj/vending_restock.dmi index 035c01de6b..978a13803c 100644 Binary files a/icons/obj/vending_restock.dmi and b/icons/obj/vending_restock.dmi differ diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi index c8675209c4..d24efa0625 100644 Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ diff --git a/interface/skin.dmf b/interface/skin.dmf index 04a78af061..8d68336754 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -54,6 +54,7 @@ window "mainwindow" size = 640x440 anchor1 = none anchor2 = none + background-color = #242424 is-default = true saved-params = "pos;size;is-minimized;is-maximized" icon = 'icons\\ss13_64.png' @@ -61,60 +62,23 @@ window "mainwindow" menu = "menu" elem "split" type = CHILD - pos = 3,0 - size = 634x417 + pos = 0,0 + size = 637x440 anchor1 = 0,0 anchor2 = 100,100 + background-color = #272727 saved-params = "splitter" left = "mapwindow" right = "infowindow" is-vert = true - elem "input" - type = INPUT - pos = 3,420 - size = 517x20 - anchor1 = 0,100 - anchor2 = 100,100 - background-color = #d3b5b5 - is-default = true - border = sunken - saved-params = "command" - elem "saybutton" - type = BUTTON - pos = 600,420 - size = 40x20 - anchor1 = 100,100 - anchor2 = none - saved-params = "is-checked" - text = "Chat" - command = ".winset \"saybutton.is-checked=true ? input.command=\"!say \\\"\" : input.command=\"\"saybutton.is-checked=true ? mebutton.is-checked=false\"\"saybutton.is-checked=true ? oocbutton.is-checked=false\"" - button-type = pushbox - elem "oocbutton" - type = BUTTON - pos = 520,420 - size = 40x20 - anchor1 = 100,100 - anchor2 = none - saved-params = "is-checked" - text = "OOC" - command = ".winset \"oocbutton.is-checked=true ? input.command=\"!ooc \\\"\" : input.command=\"\"oocbutton.is-checked=true ? mebutton.is-checked=false\"\"oocbutton.is-checked=true ? saybutton.is-checked=false\"" - button-type = pushbox - elem "mebutton" - type = BUTTON - pos = 560,420 - size = 40x20 - anchor1 = 100,100 - anchor2 = none - saved-params = "is-checked" - text = "Me" - command = ".winset \"mebutton.is-checked=true ? input.command=\"!me \\\"\" : input.command=\"\"mebutton.is-checked=true ? saybutton.is-checked=false\"\"mebutton.is-checked=true ? oocbutton.is-checked=false\"" - button-type = pushbox + splitter = 75 elem "asset_cache_browser" type = BROWSER pos = 0,0 size = 200x200 anchor1 = none anchor2 = none + background-color = #272727 is-visible = false saved-params = "" elem "tooltip" @@ -123,6 +87,7 @@ window "mainwindow" size = 999x999 anchor1 = none anchor2 = none + background-color = #272727 is-visible = false saved-params = "" @@ -134,11 +99,11 @@ window "mapwindow" anchor1 = none anchor2 = none background-color = none - saved-params = "" + saved-params = "pos;size;is-minimized;is-maximized" statusbar = false is-pane = true - outer-size = 1090x1192 - inner-size = 1068x1136 + outer-size = 684x617 + inner-size = 662x561 elem "map" type = MAP pos = 0,0 @@ -159,6 +124,7 @@ window "infowindow" size = 640x480 anchor1 = none anchor2 = none + background-color = #242424 saved-params = "pos;size;is-minimized;is-maximized" is-pane = true elem "info" @@ -167,6 +133,7 @@ window "infowindow" size = 640x445 anchor1 = 0,0 anchor2 = 100,100 + background-color = #272727 saved-params = "splitter" left = "statwindow" right = "outputwindow" @@ -177,6 +144,8 @@ window "infowindow" size = 104x20 anchor1 = 3,0 anchor2 = 19,0 + text-color = #e0e0e0 + background-color = #40628a saved-params = "is-checked" text = "Changelog" command = "changelog" @@ -186,6 +155,8 @@ window "infowindow" size = 100x20 anchor1 = 19,0 anchor2 = 34,0 + text-color = #e0e0e0 + background-color = #40628a saved-params = "is-checked" text = "Rules" command = "rules" @@ -195,6 +166,8 @@ window "infowindow" size = 100x20 anchor1 = 34,0 anchor2 = 50,0 + text-color = #e0e0e0 + background-color = #40628a saved-params = "is-checked" text = "Wiki" command = "wiki" @@ -204,6 +177,8 @@ window "infowindow" size = 100x20 anchor1 = 50,0 anchor2 = 66,0 + text-color = #e0e0e0 + background-color = #40628a saved-params = "is-checked" text = "Forum" command = "forum" @@ -213,8 +188,10 @@ window "infowindow" size = 100x20 anchor1 = 66,0 anchor2 = 81,0 + text-color = #e0e0e0 + background-color = #40628a saved-params = "is-checked" - text = "Github" + text = "GitHub" command = "github" elem "report-issue" type = BUTTON @@ -222,6 +199,9 @@ window "infowindow" size = 100x20 anchor1 = 81,0 anchor2 = 97,0 + font-size = 8 + text-color = #e0e0e0 + background-color = #a92c2c saved-params = "is-checked" text = "Report Issue" command = "report-issue" @@ -233,15 +213,44 @@ window "outputwindow" size = 640x480 anchor1 = none anchor2 = none + background-color = #272727 saved-params = "pos;size;is-minimized;is-maximized" + titlebar = false + statusbar = false + can-close = false + can-minimize = false + can-resize = false is-pane = true + elem "input" + type = INPUT + pos = 2,460 + size = 595x20 + anchor1 = 0,100 + anchor2 = 100,100 + background-color = #d3b5b5 + is-default = true + border = sunken + saved-params = "command" + elem "say" + type = BUTTON + pos = 600,460 + size = 37x20 + anchor1 = 100,100 + anchor2 = none + text-color = #e0e0e0 + background-color = #272727 + saved-params = "is-checked" + text = "Chat" + command = ".winset \"say.is-checked=true ? input.command=\"!say \\\"\" : input.command=\"" + is-flat = true + button-type = pushbox elem "browseroutput" type = BROWSER pos = 0,0 - size = 640x480 + size = 640x456 anchor1 = 0,0 anchor2 = 100,100 - background-color = #ffffff + background-color = #272727 is-visible = false is-disabled = true saved-params = "" @@ -249,19 +258,22 @@ window "outputwindow" elem "output" type = OUTPUT pos = 0,0 - size = 640x480 + size = 640x456 anchor1 = 0,0 anchor2 = 100,100 + text-color = #e0e0e0 + background-color = #272727 is-default = true saved-params = "" window "statwindow" elem "statwindow" type = MAIN - pos = 0,0 + pos = 281,0 size = 640x480 anchor1 = none anchor2 = none + background-color = #242424 saved-params = "pos;size;is-minimized;is-maximized" is-pane = true elem "stat" @@ -270,8 +282,14 @@ window "statwindow" size = 640x480 anchor1 = 0,0 anchor2 = 100,100 + text-color = #e0e0e0 + background-color = #272727 is-default = true saved-params = "" + tab-text-color = #e0e0e0 + tab-background-color = #242424 + prefix-color = #e0e0e0 + suffix-color = #e0e0e0 window "preferences_window" elem "preferences_window" diff --git a/modular_citadel/code/__HELPERS/list2list.dm b/modular_citadel/code/__HELPERS/list2list.dm deleted file mode 100644 index e812b3a1e9..0000000000 --- a/modular_citadel/code/__HELPERS/list2list.dm +++ /dev/null @@ -1,12 +0,0 @@ -/proc/tg_ui_icon_to_cit_ui(ui_style) - switch(ui_style) - if('icons/mob/screen_plasmafire.dmi') - return 'modular_citadel/icons/ui/screen_plasmafire.dmi' - if('icons/mob/screen_slimecore.dmi') - return 'modular_citadel/icons/ui/screen_slimecore.dmi' - if('icons/mob/screen_operative.dmi') - return 'modular_citadel/icons/ui/screen_operative.dmi' - if('icons/mob/screen_clockwork.dmi') - return 'modular_citadel/icons/ui/screen_clockwork.dmi' - else - return 'modular_citadel/icons/ui/screen_midnight.dmi' diff --git a/modular_citadel/code/__HELPERS/lists.dm b/modular_citadel/code/__HELPERS/lists.dm deleted file mode 100644 index b249dfc554..0000000000 --- a/modular_citadel/code/__HELPERS/lists.dm +++ /dev/null @@ -1,9 +0,0 @@ -/proc/is_type_in_ref_list(path, list/L) - if(!ispath(path))//not a path - return - for(var/i in L) - var/datum/D = i - if(!istype(D))//not an usable reference - continue - if(istype(D, path)) - return TRUE \ No newline at end of file diff --git a/modular_citadel/code/__HELPERS/mobs.dm b/modular_citadel/code/__HELPERS/mobs.dm deleted file mode 100644 index 2666696564..0000000000 --- a/modular_citadel/code/__HELPERS/mobs.dm +++ /dev/null @@ -1,28 +0,0 @@ -/proc/slot_to_string(slot) - switch(slot) - if(SLOT_BACK) - return "Backpack" - if(SLOT_WEAR_MASK) - return "Mask" - if(SLOT_HANDS) - return "Hands" - if(SLOT_BELT) - return "Belt" - if(SLOT_EARS) - return "Ears" - if(SLOT_GLASSES) - return "Glasses" - if(SLOT_GLOVES) - return "Gloves" - if(SLOT_NECK) - return "Neck" - if(SLOT_HEAD) - return "Head" - if(SLOT_SHOES) - return "Shoes" - if(SLOT_WEAR_SUIT) - return "Suit" - if(SLOT_W_UNIFORM) - return "Uniform" - if(SLOT_IN_BACKPACK) - return "In backpack" diff --git a/modular_citadel/code/_onclick/click.dm b/modular_citadel/code/_onclick/click.dm index f077b3a71b..004cc2fe80 100644 --- a/modular_citadel/code/_onclick/click.dm +++ b/modular_citadel/code/_onclick/click.dm @@ -72,30 +72,3 @@ /mob/proc/AltRangedAttack(atom/A, params) return FALSE - -/mob/proc/mouse_face_atom(atom/A) //Basically a copy of face_atom but with ismousemovement set to TRUE - if( buckled || stat != CONSCIOUS || !A || !x || !y || !A.x || !A.y ) - return - var/dx = A.x - x - var/dy = A.y - y - if(!dx && !dy) // Wall items are graphically shifted but on the floor - if(A.pixel_y > 16) - setDir(NORTH, ismousemovement = TRUE) - else if(A.pixel_y < -16) - setDir(SOUTH, ismousemovement = TRUE) - else if(A.pixel_x > 16) - setDir(EAST, ismousemovement = TRUE) - else if(A.pixel_x < -16) - setDir(WEST, ismousemovement = TRUE) - return - - if(abs(dx) < abs(dy)) - if(dy > 0) - setDir(NORTH, ismousemovement = TRUE) - else - setDir(SOUTH, ismousemovement = TRUE) - else - if(dx > 0) - setDir(EAST, ismousemovement = TRUE) - else - setDir(WEST, ismousemovement = TRUE) diff --git a/modular_citadel/code/_onclick/hud/screen_objects.dm b/modular_citadel/code/_onclick/hud/screen_objects.dm index 2101a6045f..a2fa6ee23c 100644 --- a/modular_citadel/code/_onclick/hud/screen_objects.dm +++ b/modular_citadel/code/_onclick/hud/screen_objects.dm @@ -1,13 +1,3 @@ -/obj/screen/restbutton - name = "rest" - icon = 'modular_citadel/icons/ui/screen_midnight.dmi' - icon_state = "rest" - -/obj/screen/restbutton/Click() - if(isliving(usr)) - var/mob/living/theuser = usr - theuser.lay_down() - /obj/screen/combattoggle name = "toggle combat mode" icon = 'modular_citadel/icons/ui/screen_midnight.dmi' diff --git a/modular_citadel/code/_onclick/other_mobs.dm b/modular_citadel/code/_onclick/other_mobs.dm index 6d9ffdd6ca..ec740f023b 100644 --- a/modular_citadel/code/_onclick/other_mobs.dm +++ b/modular_citadel/code/_onclick/other_mobs.dm @@ -12,7 +12,7 @@ if(isturf(A) || incapacitated()) // pretty annoying to wave your fist at floors and walls. And useless. return TRUE changeNext_move(CLICK_CD_RANGE) - var/list/target_viewers = viewers(11, A) //Byond proc, doesn't check for blindness. + var/list/target_viewers = fov_viewers(11, A) //doesn't check for blindness. if(!(src in target_viewers)) //click catcher issuing calls for out of view objects. return TRUE if(!has_active_hand()) @@ -26,16 +26,16 @@ switch(a_intent) if(INTENT_DISARM) the_action = "shoos away [A]" - what_action = "shoo away something you can't see" + what_action = "shoo away something out of your vision" self_action = "shoo away [A]" if(INTENT_GRAB) the_action = "beckons [A] to come" - what_action = "beckons something you can't see to come" + what_action = "beckons something out of your vision to come" self_action = "beckon [A] to come" if(INTENT_HARM) var/pronoun = "[p_their()]" the_action = "shakes [pronoun] fist at [A]" - what_action = "shakes [pronoun] fist at something you can't see" + what_action = "shakes [pronoun] fist at something out of your vision" self_action = "shake your fist at [A]" if(!eye_blind) diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index 62fe30f2d7..57cbdb6beb 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -10,7 +10,7 @@ alert_type = null /datum/status_effect/chem/SGDF/on_apply() - log_game("FERMICHEM: SGDF status appied on [owner], ID: [owner.key]") + log_reagent("FERMICHEM: SGDF status appied on [owner], ID: [owner.key]") fermi_Clone = owner return ..() @@ -24,7 +24,7 @@ ..() /datum/status_effect/chem/SGDF/on_remove() - log_game("FERMICHEM: SGDF mind shift applied. [owner] is now playing as their clone and should not have memories after their clone split (look up SGDF status applied). ID: [owner.key]") + log_reagent("FERMICHEM: SGDF mind shift applied. [owner] is now playing as their clone and should not have memories after their clone split (look up SGDF status applied). ID: [owner.key]") originalmind.transfer_to(fermi_Clone) to_chat(owner, "Lucidity shoots to your previously blank mind as your mind suddenly finishes the cloning process. You marvel for a moment at yourself, as your mind subconciously recollects all your memories up until the point when you cloned yourself. Curiously, you find that you memories are blank after you ingested the synthetic serum, leaving you to wonder where the other you is.") fermi_Clone = null @@ -40,7 +40,7 @@ var/last_checked_size //used to prevent potential cpu waste from happening every tick. /datum/status_effect/chem/breast_enlarger/on_apply()//Removes clothes, they're too small to contain you. You belong to space now. - log_game("FERMICHEM: [owner]'s breasts has reached comical sizes. ID: [owner.key]") + log_reagent("FERMICHEM: [owner]'s breasts has reached comical sizes. ID: [owner.key]") var/mob/living/carbon/human/H = owner var/message = FALSE if(H.w_uniform) @@ -91,7 +91,7 @@ ..() /datum/status_effect/chem/breast_enlarger/on_remove() - log_game("FERMICHEM: [owner]'s breasts has reduced to an acceptable size. ID: [owner.key]") + log_reagent("FERMICHEM: [owner]'s breasts has reduced to an acceptable size. ID: [owner.key]") to_chat(owner, "Your expansive chest has become a more managable size, liberating your movements.") owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/breast_hypertrophy) sizeMoveMod(1) @@ -114,7 +114,7 @@ var/last_checked_size //used to prevent potential cpu waste, just like the above. /datum/status_effect/chem/penis_enlarger/on_apply()//Removes clothes, they're too small to contain you. You belong to space now. - log_game("FERMICHEM: [owner]'s dick has reached comical sizes. ID: [owner.key]") + log_reagent("FERMICHEM: [owner]'s dick has reached comical sizes. ID: [owner.key]") var/mob/living/carbon/human/H = owner var/message = FALSE if(H.w_uniform) @@ -162,7 +162,7 @@ ..() /datum/status_effect/chem/penis_enlarger/on_remove() - log_game("FERMICHEM: [owner]'s dick has reduced to an acceptable size. ID: [owner.key]") + log_reagent("FERMICHEM: [owner]'s dick has reduced to an acceptable size. ID: [owner.key]") owner.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/penis_hypertrophy) owner.ResetBloodVol() return ..() @@ -189,7 +189,7 @@ var/mob/living/simple_animal/astral/G = new(get_turf(M.loc)) owner.mind.transfer_to(G)//Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end. to_chat(G, "[M]'s conciousness snaps back to them as their astrogen runs out, kicking your projected mind out!'") - log_game("FERMICHEM: [M]'s possesser has been booted out into a astral ghost!") + log_reagent("FERMICHEM: [M]'s possesser has been booted out into a astral ghost!") originalmind.transfer_to(original) /datum/status_effect/chem/astral_insurance/on_remove() //God damnit get them home! @@ -198,7 +198,7 @@ var/mob/living/simple_animal/astral/G = new(get_turf(owner)) owner.mind.transfer_to(G)//Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end. to_chat(G, "[owner]'s conciousness snaps back to them as their astrogen runs out, kicking your projected mind out!'") - log_game("FERMICHEM: [owner]'s possesser has been booted out into a astral ghost!") + log_reagent("FERMICHEM: [owner]'s possesser has been booted out into a astral ghost!") originalmind.transfer_to(original) return ..() @@ -272,7 +272,7 @@ var/message = "[(lewd ? "I am a good pet for [enthrallGender]." : "[master] is a really inspirational person!")]" SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "enthrall", /datum/mood_event/enthrall, message) to_chat(owner, "You feel inexplicably drawn towards [master], their words having a demonstrable effect on you. It seems the closer you are to them, the stronger the effect is. However you aren't fully swayed yet and can resist their effects by repeatedly resisting as much as you can!") - log_game("FERMICHEM: MKULTRA: Status applied on [owner] ckey: [owner.key] with a master of [master] ckey: [enthrallID].") + log_reagent("FERMICHEM: MKULTRA: Status applied on [owner] ckey: [owner.key] with a master of [master] ckey: [enthrallID].") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Enthrall attempts") return ..() @@ -303,7 +303,7 @@ switch(phase) if(-1)//fully removed SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "enthrall") - log_game("FERMICHEM: MKULTRA: Status REMOVED from [owner] ckey: [owner.key] with a master of [master] ckey: [enthrallID].") + log_reagent("FERMICHEM: MKULTRA: Status REMOVED from [owner] ckey: [owner.key] with a master of [master] ckey: [enthrallID].") owner.remove_status_effect(src) return if(0)// sleeper agent @@ -344,7 +344,7 @@ else to_chat(owner, "You are unable to put up a resistance any longer, and now are under the influence of [master]. However you find that in your intoxicated state you are unable to resort to violence. Equally you are unable to commit suicide, even if ordered to, as you cannot follow [master] in death. ") to_chat(master, "Your [(lewd?"pet":"follower")] [owner] appears to have fully fallen under your sway.") - log_game("FERMICHEM: MKULTRA: Status on [owner] ckey: [owner.key] has been fully entrhalled (state 3) with a master of [master] ckey: [enthrallID].") + log_reagent("FERMICHEM: MKULTRA: Status on [owner] ckey: [owner.key] has been fully entrhalled (state 3) with a master of [master] ckey: [enthrallID].") SSblackbox.record_feedback("tally", "fermi_chem", 1, "thralls fully enthralled.") else if (resistanceTally > 200) enthrallTally *= 0.5 @@ -616,14 +616,14 @@ var/cached_trigger = lowertext(trigger) if (findtext(raw_message, cached_trigger))//if trigger1 is the message cTriggered = 5 //Stops triggerparties and as a result, stops servercrashes. - log_game("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been triggered with [cached_trigger] from [hearing_args[HEARING_SPEAKER]] saying: \"[hearing_args[HEARING_MESSAGE]]\". (their master being [master] ckey: [enthrallID].)") + log_reagent("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been triggered with [cached_trigger] from [hearing_args[HEARING_SPEAKER]] saying: \"[hearing_args[HEARING_MESSAGE]]\". (their master being [master] ckey: [enthrallID].)") //Speak (Forces player to talk) if (lowertext(customTriggers[trigger][1]) == "speak")//trigger2 var/saytext = "Your mouth moves on it's own before you can even catch it." addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "[saytext]"), 5) addtimer(CALLBACK(C, /atom/movable/proc/say, "[customTriggers[trigger][2]]"), 5) - log_game("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been forced to say: \"[customTriggers[trigger][2]]\" from previous trigger.") + log_reagent("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been forced to say: \"[customTriggers[trigger][2]]\" from previous trigger.") //Echo (repeats message!) allows customisation, but won't display var calls! Defaults to hypnophrase. @@ -671,7 +671,7 @@ var/mob/living/carbon/human/o = owner o.apply_status_effect(/datum/status_effect/trance, 200, TRUE) tranceTime = 50 - log_game("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been tranced from previous trigger.") + log_reagent("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been tranced from previous trigger.") return diff --git a/modular_citadel/code/game/machinery/wishgranter.dm b/modular_citadel/code/game/machinery/wishgranter.dm deleted file mode 100644 index 6cfe07b7a0..0000000000 --- a/modular_citadel/code/game/machinery/wishgranter.dm +++ /dev/null @@ -1,122 +0,0 @@ -/obj/machinery/wish_granter/attack_hand(mob/living/carbon/user) - if(charges <= 0) - to_chat(user, "The Wish Granter lies silent.") - return - - else if(!ishuman(user)) - to_chat(user, "You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.") - return - - else if (!insisting) - to_chat(user, "Your first touch makes the Wish Granter stir, listening to you. Are you really sure you want to do this?") - insisting++ - - else - if(is_special_character(user)) - to_chat(user, "You speak. [pick("I want power","Humanity is corrupt, mankind must be destroyed", "I want to rule the world","I want immortality")]. The Wish Granter answers.") - to_chat(user, "Your head pounds for a moment, before your vision clears. The Wish Granter, sensing the darkness in your heart, has given you limitless power, and it's all yours!") - user.dna.add_mutation(HULK) - user.dna.add_mutation(XRAY) - user.dna.add_mutation(SPACEMUT) - user.dna.add_mutation(TK) - user.next_move_modifier *= 0.5 //half the delay between attacks! - to_chat(user, "Things around you feel slower!") - charges-- - insisting = FALSE - to_chat(user, "You have a very great feeling about this!") - else - to_chat(user, "The Wish Granter awaits your wish.") - var/wish = input("You want...","Wish") as null|anything in list("Power","Wealth","The Station To Disappear","To Kill","Nothing") - switch(wish) - if("Power") //Gives infinite power in exchange for infinite power going off in your face! - if(charges <= 0) - return - to_chat(user, "Your wish is granted, but at a terrible cost...") - to_chat(user, "The Wish Granter punishes you for your selfishness, warping itself into a delaminating supermatter shard!") - var/obj/item/stock_parts/cell/infinite/powah = new /obj/item/stock_parts/cell/infinite(get_turf(user)) - if(user.put_in_hands(powah)) - to_chat(user, "[powah] materializes into your hands!") - else - to_chat(user, "[powah] materializes onto the floor.") - var/obj/machinery/power/supermatter_crystal/powerwish = new /obj/machinery/power/supermatter_crystal(loc) - powerwish.damage = 700 //right at the emergency threshold - powerwish.produces_gas = FALSE - charges-- - insisting = FALSE - if(!charges) - qdel(src) - if("Wealth") //Gives 1 million space bucks in exchange for being turned into gold! - if(charges <= 0) - return - to_chat(user, "Your wish is granted, but at a cost...") - to_chat(user, "The Wish Granter punishes you for your selfishness, warping your body to match the greed in your heart.") - new /obj/structure/closet/crate/trashcart/moneywish(loc) - new /obj/structure/closet/crate/trashcart/moneywish(loc) - user.set_species(/datum/species/golem/gold) - charges-- - insisting = FALSE - if(!charges) - qdel(src) - if("The Station To Disappear") //teleports you to the station and makes you blind, making the station disappear for you! - if(charges <= 0) - return - to_chat(user, "Your wish is 'granted', but at a terrible cost...") - to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your eyes to match the darkness in your heart.") - user.dna.add_mutation(BLINDMUT) - var/obj/item/organ/eyes/eyes = user.getorganslot(ORGAN_SLOT_EYES) - if(eyes) - eyes.applyOrganDamage(eyes.maxHealth) - var/list/destinations = list() - for(var/obj/item/beacon/B in GLOB.teleportbeacons) - var/turf/T = get_turf(B) - if(is_station_level(T.z)) - destinations += B - var/chosen_beacon = pick(destinations) - var/obj/effect/portal/jaunt_tunnel/J = new (get_turf(src), src, 100, null, FALSE, get_turf(chosen_beacon)) - try_move_adjacent(J) - playsound(src,'sound/effects/sparks4.ogg',50,1) - charges-- - insisting = FALSE - if(!charges) - qdel(src) - if("To Kill") //Makes you kill things in exchange for rewards! - if(charges <= 0) - return - to_chat(user, "Your wish is granted, but at a terrible cost...") - to_chat(user, "The Wish Granter punishes you for your wickedness, warping itself into a dastardly creature for you to kill! ...but it almost seems to reward you for this.") - var/obj/item/melee/transforming/energy/sword/cx/killreward = new /obj/item/melee/transforming/energy/sword/cx(get_turf(user)) - if(user.put_in_hands(killreward)) - to_chat(user, "[killreward] materializes into your hands!") - else - to_chat(user, "[killreward] materializes onto the floor.") - user.next_move_modifier *= 0.8 //20% less delay between attacks! - to_chat(user, "Things around you feel slightly slower!") - var/mob/living/simple_animal/hostile/venus_human_trap/killwish = new /mob/living/simple_animal/hostile/venus_human_trap(loc) - killwish.maxHealth = 1500 - killwish.health = killwish.maxHealth - killwish.vine_grab_distance = 6 - killwish.melee_damage_upper = 30 - killwish.loot = list(/obj/item/twohanded/dualsaber/hypereutactic) - charges-- - insisting = FALSE - if(!charges) - qdel(src) - if("Nothing") //Makes the wish granter disappear - if(charges <= 0) - return - to_chat(user, "The Wish Granter vanishes from sight!") - to_chat(user, "You feel as if you just narrowly avoided a terrible fate...") - charges-- - insisting = FALSE - qdel(src) - -//ITEMS THAT IT USES - -/obj/structure/closet/crate/trashcart/moneywish - desc = "A heavy, metal trashcart with wheels. Filled with cash." - name = "loaded trash cart" - -/obj/structure/closet/crate/trashcart/moneywish/PopulateContents() //25*20*1000=500,000 - for(var/i = 0, i < 25, i++) - var/obj/item/stack/spacecash/c1000/lodsamoney = new /obj/item/stack/spacecash/c1000(src) - lodsamoney.amount = lodsamoney.max_amount diff --git a/modular_citadel/code/game/objects/items/devices/radio/shockcollar.dm b/modular_citadel/code/game/objects/items/devices/radio/shockcollar.dm deleted file mode 100644 index 6c9f12a852..0000000000 --- a/modular_citadel/code/game/objects/items/devices/radio/shockcollar.dm +++ /dev/null @@ -1,83 +0,0 @@ -/obj/item/electropack/shockcollar - name = "shock collar" - desc = "A reinforced metal collar. It seems to have some form of wiring near the front. Strange.." - icon = 'modular_citadel/icons/obj/clothing/cit_neck.dmi' - mob_overlay_icon = 'modular_citadel/icons/mob/citadel/neck.dmi' - icon_state = "shockcollar" - item_state = "shockcollar" - body_parts_covered = NECK - slot_flags = ITEM_SLOT_NECK | ITEM_SLOT_DENYPOCKET //no more pocket shockers - w_class = WEIGHT_CLASS_SMALL - strip_delay = 60 - equip_delay_other = 60 - materials = list(MAT_METAL=5000, MAT_GLASS=2000) - var/tagname = null - -/datum/design/electropack/shockcollar - name = "Shockcollar" - id = "shockcollar" - build_type = AUTOLATHE - build_path = /obj/item/electropack/shockcollar - materials = list(MAT_METAL=5000, MAT_GLASS=2000) - category = list("hacked", "Misc") - -/obj/item/electropack/shockcollar/attack_hand(mob/user) - if(loc == user && user.get_item_by_slot(SLOT_NECK)) - to_chat(user, "The collar is fastened tight! You'll need help taking this off!") - return - ..() - -/obj/item/electropack/shockcollar/receive_signal(datum/signal/signal) - if(!signal || signal.data["code"] != code) - return - - if(isliving(loc) && on) - if(shock_cooldown != 0) - return - shock_cooldown = 1 - spawn(100) - shock_cooldown = 0 - var/mob/living/L = loc - step(L, pick(GLOB.cardinals)) - - to_chat(L, "You feel a sharp shock from the collar!") - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(3, 1, L) - s.start() - - L.DefaultCombatKnockdown(100) - - if(master) - master.receive_signal() - return - -/obj/item/electropack/shockcollar/attack_self(mob/user) //Turns out can't fully source this from the parent item, spritepath gets confused if power toggled. Will come back to this when I know how to code better and readd powertoggle.. - var/option = "Change Name" - option = input(user, "What do you want to do?", "[src]", option) as null|anything in list("Change Name", "Change Frequency") - switch(option) - if("Change Name") - var/t = input(user, "Would you like to change the name on the tag?", "Name your new pet", tagname ? tagname : "Spot") as null|text - if(t) - tagname = copytext(sanitize(t), 1, MAX_NAME_LEN) - name = "[initial(name)] - [tagname]" - if("Change Frequency") - if(!ishuman(user)) - return - user.set_machine(src) - var/dat = {"
- Frequency/Code for shock collar:
- Frequency: - - - - [format_frequency(frequency)] - + - +
- Code: - - - - [code] - + - +
-
"} - - user << browse(dat, "window=radio") - onclose(user, "radio") - return diff --git a/modular_citadel/code/game/objects/structures/beds_chairs/chair.dm b/modular_citadel/code/game/objects/structures/beds_chairs/chair.dm deleted file mode 100644 index 5b20fe048b..0000000000 --- a/modular_citadel/code/game/objects/structures/beds_chairs/chair.dm +++ /dev/null @@ -1,21 +0,0 @@ -/obj/structure/chair/alt_attack_hand(mob/living/user) - if(Adjacent(user) && istype(user)) - if(!item_chair || !user.can_hold_items() || !has_buckled_mobs() || buckled_mobs.len > 1 || dir != user.dir || flags_1 & NODECONSTRUCT_1) - return TRUE - if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user))) - to_chat(user, "You can't do that right now!") - return TRUE - if(user.getStaminaLoss() >= STAMINA_SOFTCRIT) - to_chat(user, "You're too exhausted for that.") - return TRUE - var/mob/living/poordude = buckled_mobs[1] - if(!istype(poordude)) - return TRUE - user.visible_message("[user] pulls [src] out from under [poordude].", "You pull [src] out from under [poordude].") - var/C = new item_chair(loc) - user.put_in_hands(C) - poordude.DefaultCombatKnockdown(20)//rip in peace - user.adjustStaminaLoss(5) - unbuckle_all_mobs(TRUE) - qdel(src) - return TRUE diff --git a/modular_citadel/code/modules/admin/chat_commands.dm b/modular_citadel/code/modules/admin/chat_commands.dm deleted file mode 100644 index ddac7b5953..0000000000 --- a/modular_citadel/code/modules/admin/chat_commands.dm +++ /dev/null @@ -1,46 +0,0 @@ -/datum/tgs_chat_command/wheelofsalt - name = "wheelofsalt" - help_text = "What are Citadel Station 13 players salting about today? Spin the wheel and find out!" - -/datum/tgs_chat_command/wheelofsalt/Run(datum/tgs_chat_user/sender, params) - var/saltresult = "The wheel of salt [pick("clatters","screams","vibrates","clanks","resonates","groans","moans","squeaks","emits a[pick(" god-forsaken"," lewd"," creepy"," generic","n orgasmic"," demonic")] [pick("airhorn","bike horn","trumpet","clown","latex","vore","dog","laughing")] noise")] as it spins violently... And it seems the salt of the day is the " - var/saltprimarysubject = "[pick("combat","medical","grab","furry","wall","orgasm","cat","ERP","lizard","dog","latex","vision cone","atmospherics","table","chem","vore","dogborg","Skylar Lineman","Mekhi Anderson","Peppermint","rework","cum","dick","cockvore","Medihound","sleeper","belly sleeper","door wires","flightsuit","coder privilege","Developer abuse","ban reason","github self merge","red panda","beret","male catgirl","powergame","hexacrocin","Discord server","Clitadel","Cargonia","Solarian Republic","Main and RP merger","bluespace","salt","chem dispenser theft","Botany","moth","BWOINK","anal vore","stamina","Mason Jakops","mining","noodle","milf","Lavaland","Necropolis","Ashwalker","Chase Redtail","Drew Mint","Pavel Marsk","Joker Amari","Durgit","chaplain","Antag","nanite","Syndicate","Nar-Sie","Ratvar","Cult","maint","Foam-Force","AI","cyborg","ghost","clockwork","cyberpunk","vaporwave","Clown","Leon Beech","Mime","security","research","Megafauna","Bubblegum","Ash Drake","Legion","Colossus","White Shuttle","Changeling","Cowboy","Space Ninja","Poly","Revolutionary","Skyrim","forbidden fruits","xenomorph","blob","Nuclear Operative","crossdressing")]" - var/saltsecondarysubject = "[pick("rework","changes","r34","ban","removal","addition","leak","proposal","fanart","introduction","tabling","ERP","bikeshedding","crossdressing","sprites","semen keg","argument","theft","nerf","screeching","salt","creampie","lewding","murder","kissing","marriage","replacement","fucking","ship","netflix adaptation","dance","remaster","system","voyeur","decoration","pre-order","bukkake","seduction","worship","gangbang","handholding")]" - if(prob(10)) - saltresult += "@here for your salt, all day every day" - if(prob(1)) - saltresult += " @everyone gets some salt this time too" - else - saltresult += "[saltprimarysubject] [saltsecondarysubject]" - return "[saltresult]!" - -/datum/tgs_chat_command/valentine - name = "valentine" - help_text = "Get a random flirt line." - -/datum/tgs_chat_command/valentine/Run(datum/tgs_chat_user/sender, params) - return "[pick(GLOB.flirts)]" - -/datum/tgs_chat_command/despacito - name = "despacito" //someone please high effort this sometime and make it a full on ytdl search - help_text = "This is so sad." - -/datum/tgs_chat_command/despacito/Run() - return "https://www.youtube.com/watch?v=kJQP7kiw5Fk" - -/datum/tgs_chat_command/poly - name = "poly" - help_text = "The Lewder, more applicable Poly speak for Citadel Station 13." - var/list/speech_buffer - -/datum/tgs_chat_command/poly/Run() - LAZYINITLIST(speech_buffer) //I figure this is just safe to do for everything at this point - if(length(speech_buffer)) //Let's not look up the whole json EVERY TIME, just the first time. - return "[pick(speech_buffer)]" - else - var/json_file = file("data/npc_saves/Poly.json") - if(!fexists(json_file)) - return "**BAWWWWWK!** LEAVE THE HEADSET! ***BAWKKKKK!!***" - var/list/json = json_decode(file2text(json_file)) - speech_buffer = json["phrases"] - return "[pick(speech_buffer)]" diff --git a/modular_citadel/code/modules/client/client_defines.dm b/modular_citadel/code/modules/client/client_defines.dm deleted file mode 100644 index d816b15d1d..0000000000 --- a/modular_citadel/code/modules/client/client_defines.dm +++ /dev/null @@ -1,2 +0,0 @@ -/client - var/cryo_warned = -3000//when was the last time we warned them about not cryoing without an ahelp, set to -5 minutes so that rounstart cryo still warns diff --git a/modular_citadel/code/modules/client/loadout/_loadout.dm b/modular_citadel/code/modules/client/loadout/_loadout.dm index d35bede179..51256f8cde 100644 --- a/modular_citadel/code/modules/client/loadout/_loadout.dm +++ b/modular_citadel/code/modules/client/loadout/_loadout.dm @@ -10,7 +10,6 @@ GLOBAL_LIST_EMPTY(loadout_whitelist_ids) /proc/load_loadout_config(loadout_config) if(!loadout_config) loadout_config = "config/loadout_config.txt" - LAZYINITLIST(GLOB.loadout_whitelist_ids) var/list/file_lines = world.file2list(loadout_config) for(var/line in file_lines) if(!line || line[1] == "#") @@ -26,12 +25,9 @@ GLOBAL_LIST_EMPTY(loadout_whitelist_ids) GLOB.loadout_whitelist_ids["[lineID]"] = sublinecontent /proc/initialize_global_loadout_items() - LAZYINITLIST(GLOB.loadout_items) load_loadout_config() for(var/item in subtypesof(/datum/gear)) var/datum/gear/I = new item - if(!GLOB.loadout_items[slot_to_string(I.category)]) - LAZYINITLIST(GLOB.loadout_items[slot_to_string(I.category)]) LAZYSET(GLOB.loadout_items[slot_to_string(I.category)], I.name, I) if(islist(I.geargroupID)) var/list/ggidlist = I.geargroupID diff --git a/modular_citadel/code/modules/client/loadout/backpack.dm b/modular_citadel/code/modules/client/loadout/backpack.dm index d51f4b6125..8d089a129a 100644 --- a/modular_citadel/code/modules/client/loadout/backpack.dm +++ b/modular_citadel/code/modules/client/loadout/backpack.dm @@ -69,18 +69,6 @@ path = /obj/item/toy/katana cost = 3 -/datum/gear/box - name = "Spare box" - category = SLOT_IN_BACKPACK - path = /obj/item/storage/box - cost = 2 - -/datum/gear/crowbar - name = "Pocket Crowbar" - category = SLOT_IN_BACKPACK - path = /obj/item/crowbar - cost = 2 - /datum/gear/tapeplayer name = "Taperecorder" category = SLOT_IN_BACKPACK @@ -96,11 +84,6 @@ category = SLOT_IN_BACKPACK path = /obj/item/newspaper -/datum/gear/paperbin - name = "Paper Bin" - category = SLOT_IN_BACKPACK - path = /obj/item/paper_bin - /datum/gear/crayons name = "Box of crayons" category = SLOT_IN_BACKPACK @@ -146,4 +129,4 @@ category = SLOT_IN_BACKPACK path = /obj/item/storage/fancy/ringbox/diamond cost = 5 - + diff --git a/modular_citadel/code/modules/client/loadout/mask.dm b/modular_citadel/code/modules/client/loadout/mask.dm index 82824814ae..eeba06cad4 100644 --- a/modular_citadel/code/modules/client/loadout/mask.dm +++ b/modular_citadel/code/modules/client/loadout/mask.dm @@ -12,5 +12,5 @@ name = "Joy mask" category = SLOT_WEAR_MASK path = /obj/item/clothing/mask/joy - cost = 9 - + cost = 3 + diff --git a/modular_citadel/code/modules/client/loadout/suit.dm b/modular_citadel/code/modules/client/loadout/suit.dm index 9b39d006bd..64bfd34172 100644 --- a/modular_citadel/code/modules/client/loadout/suit.dm +++ b/modular_citadel/code/modules/client/loadout/suit.dm @@ -85,20 +85,18 @@ path = /obj/item/clothing/suit/hooded/wintercoat/polychromic cost = 4 //too many people with neon green coats is hard on the eyes -/* Commented out until it is "balanced" -/datum/gear/coat/sec - name = "Security winter coat" - category = SLOT_WEAR_SUIT - path = /obj/item/clothing/suit/hooded/wintercoat/security - restricted_roles = list("Head of Security", "Warden", "Detective", "Security Officer") // Reserve it to the Security Departement -*/ - /datum/gear/coat/med name = "Medical winter coat" category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat/medical restricted_roles = list("Chief Medical Officer", "Medical Doctor") // Reserve it to Medical Doctors and their boss, the Chief Medical Officer +/datum/gear/coat/paramedic + name = "Paramedic winter coat" + category = SLOT_WEAR_SUIT + path = /obj/item/clothing/suit/hooded/wintercoat/paramedic + restricted_roles = list("Chief Medical Officer", "Paramedic") // Reserve it to Paramedics and their boss, the Chief Medical Officer + /datum/gear/coat/robotics name = "Robotics winter coat" category = SLOT_WEAR_SUIT @@ -234,4 +232,4 @@ /datum/gear/christmascoatrg name = "Red and Green Christmas Coat" category = SLOT_WEAR_SUIT - path = /obj/item/clothing/suit/hooded/wintercoat/christmascoatrg \ No newline at end of file + path = /obj/item/clothing/suit/hooded/wintercoat/christmascoatrg diff --git a/modular_citadel/code/modules/client/preferences.dm b/modular_citadel/code/modules/client/preferences.dm deleted file mode 100644 index 8c55f2d9a8..0000000000 --- a/modular_citadel/code/modules/client/preferences.dm +++ /dev/null @@ -1,47 +0,0 @@ -#define DEFAULT_SLOT_AMT 2 -#define HANDS_SLOT_AMT 2 -#define BACKPACK_SLOT_AMT 4 - -/datum/preferences - //gear - var/gear_points = 10 - var/list/gear_categories - var/list/chosen_gear - var/gear_tab - - //pref vars - var/screenshake = 100 - var/damagescreenshake = 2 - var/arousable = TRUE - var/widescreenpref = TRUE - var/autostand = TRUE - var/auto_ooc = FALSE - - //vore prefs - var/toggleeatingnoise = TRUE - var/toggledigestionnoise = TRUE - var/hound_sleeper = TRUE - var/cit_toggles = TOGGLES_CITADEL - - -/datum/preferences/New(client/C) - ..() - LAZYINITLIST(chosen_gear) - -/datum/preferences/proc/is_loadout_slot_available(slot) - var/list/L - LAZYINITLIST(L) - for(var/i in chosen_gear) - var/datum/gear/G = i - var/occupied_slots = L[slot_to_string(initial(G.category))] ? L[slot_to_string(initial(G.category))] + 1 : 1 - LAZYSET(L, slot_to_string(initial(G.category)), occupied_slots) - switch(slot) - if(SLOT_IN_BACKPACK) - if(L[slot_to_string(SLOT_IN_BACKPACK)] < BACKPACK_SLOT_AMT) - return TRUE - if(SLOT_HANDS) - if(L[slot_to_string(SLOT_HANDS)] < HANDS_SLOT_AMT) - return TRUE - else - if(L[slot_to_string(slot)] < DEFAULT_SLOT_AMT) - return TRUE diff --git a/modular_citadel/code/modules/client/preferences_savefile.dm b/modular_citadel/code/modules/client/preferences_savefile.dm index d9b902656f..d0363d228f 100644 --- a/modular_citadel/code/modules/client/preferences_savefile.dm +++ b/modular_citadel/code/modules/client/preferences_savefile.dm @@ -14,17 +14,6 @@ features["mcolor2"] = sanitize_hexcolor(features["mcolor2"], 3, 0) features["mcolor3"] = sanitize_hexcolor(features["mcolor3"], 3, 0) - //gear loadout - var/text_to_load - S["loadout"] >> text_to_load - var/list/saved_loadout_paths = splittext(text_to_load, "|") - LAZYCLEARLIST(chosen_gear) - gear_points = initial(gear_points) - for(var/i in saved_loadout_paths) - var/datum/gear/path = text2path(i) - if(path) - LAZYADD(chosen_gear, path) - gear_points -= initial(path.cost) /datum/preferences/proc/cit_character_pref_save(savefile/S) //ipcs @@ -47,10 +36,3 @@ //flavor text WRITE_FILE(S["feature_flavor_text"], features["flavor_text"]) - //gear loadout - if(islist(chosen_gear)) - if(chosen_gear.len) - var/text_to_save = chosen_gear.Join("|") - S["loadout"] << text_to_save - else - S["loadout"] << "" //empty string to reset the value diff --git a/modular_citadel/code/modules/mob/living/carbon/carbon.dm b/modular_citadel/code/modules/mob/living/carbon/carbon.dm index e95948e562..0532f59afa 100644 --- a/modular_citadel/code/modules/mob/living/carbon/carbon.dm +++ b/modular_citadel/code/modules/mob/living/carbon/carbon.dm @@ -25,5 +25,5 @@ /mob/living/carbon/onMouseMove(object, location, control, params) if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) return - mouse_face_atom(object) + face_atom(object, TRUE) lastmousedir = dir diff --git a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm deleted file mode 100644 index f59d18686a..0000000000 --- a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm +++ /dev/null @@ -1,459 +0,0 @@ -/* -DOG BORG EQUIPMENT HERE -SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm ! -*/ - -/obj/item/dogborg/jaws - name = "Dogborg jaws" - desc = "The jaws of the debug errors oh god." - icon = 'icons/mob/dogborg.dmi' - flags_1 = CONDUCT_1 - force = 1 - throwforce = 0 - w_class = 3 - hitsound = 'sound/weapons/bite.ogg' - sharpness = IS_SHARP - var/stamtostunconversion = 0.1 //Total stamloss gets multiplied by this value for the help intent hard stun. Resting adds an additional 2x multiplier on top. Keep this low or so help me god. - var/stuncooldown = 4 SECONDS //How long it takes before you're able to attempt to stun a target again - var/nextstuntime - -/obj/item/dogborg/jaws/examine(mob/user) - . = ..() - if(!CONFIG_GET(flag/weaken_secborg)) - . += "Use help intent to attempt to non-lethally incapacitate the target by latching on with your maw. This is more effective against exhausted and resting targets." - -/obj/item/dogborg/jaws/big - name = "combat jaws" - desc = "The jaws of the law. Very sharp." - icon_state = "jaws" - force = 15 //Chomp chomp. Crew harm. - attack_verb = list("chomped", "bit", "ripped", "mauled", "enforced") - stamtostunconversion = 0.2 // 100*0.2*2=40. Stun's just long enough to slap on cuffs with click delay if the target is near hard stamcrit. - stuncooldown = 6 SECONDS - - -/obj/item/dogborg/jaws/small - name = "puppy jaws" - desc = "Rubberized teeth designed to protect accidental harm. Sharp enough for specialized tasks however." - icon_state = "smalljaws" - force = 6 - attack_verb = list("nibbled", "bit", "gnawed", "chomped", "nommed") - var/status = 0 - -/obj/item/dogborg/jaws/attack(atom/A, mob/living/silicon/robot/user) - if(!istype(user)) - return - if(!CONFIG_GET(flag/weaken_secborg) && user.a_intent != INTENT_HARM && istype(A, /mob/living)) - if(A == user.pulling) - to_chat(user, "You already have [A] in your jaws.") - return - if(nextstuntime >= world.time) - to_chat(user, "Your jaw servos are still recharging.") - return - nextstuntime = world.time + stuncooldown - var/mob/living/M = A - var/cachedstam = M.getStaminaLoss() - var/totalstuntime = cachedstam * stamtostunconversion * (M.lying ? 2 : 1) - if(CHECK_MOBILITY(M, MOBILITY_STAND)) - M.DefaultCombatKnockdown(cachedstam*2) //BORK BORK. GET DOWN. - M.Stun(totalstuntime) - user.do_attack_animation(A, ATTACK_EFFECT_BITE) - user.start_pulling(M, TRUE) //Yip yip. Come with. - user.changeNext_move(CLICK_CD_MELEE) - M.visible_message("[user] clamps [user.p_their()] [src] onto [M] and latches on!", "[user] clamps [user.p_their()] [src] onto you and latches on!") - if(totalstuntime >= 4 SECONDS) - playsound(usr, 'sound/effects/k9_jaw_strong.ogg', 75, FALSE, 2) //Wuff wuff. Big stun. - else - playsound(usr, 'sound/effects/k9_jaw_weak.ogg', 50, TRUE, -1) //Arf arf. Pls buff. - else - . = ..() - user.do_attack_animation(A, ATTACK_EFFECT_BITE) - -/obj/item/dogborg/jaws/small/attack_self(mob/user) - var/mob/living/silicon/robot/R = user - if(R.cell && R.cell.charge > 100) - if(R.emagged && status == 0) - name = "combat jaws" - icon_state = "jaws" - desc = "The jaws of the law." - force = 12 - attack_verb = list("chomped", "bit", "ripped", "mauled", "enforced") - stamtostunconversion = 0.15 - stuncooldown = 5 SECONDS - status = 1 - to_chat(user, "Your jaws are now [status ? "Combat" : "Pup'd"].") - else - name = "puppy jaws" - icon_state = "smalljaws" - desc = "The jaws of a small dog." - force = initial(force) - attack_verb = list("nibbled", "bit", "gnawed", "chomped", "nommed") - stamtostunconversion = initial(stamtostunconversion) - stuncooldown = initial(stuncooldown) - status = 0 - if(R.emagged) - to_chat(user, "Your jaws are now [status ? "Combat" : "Pup'd"].") - update_icon() - -//Boop - -/obj/item/analyzer/nose - name = "boop module" - icon = 'icons/mob/dogborg.dmi' - icon_state = "nose" - desc = "The BOOP module" - flags_1 = CONDUCT_1 - force = 0 - throwforce = 0 - attack_verb = list("nuzzles", "pushes", "boops") - w_class = 1 - -/obj/item/analyzer/nose/attack_self(mob/user) - user.visible_message("[user] sniffs around the air.", "You sniff the air for gas traces.") - - var/turf/location = user.loc - if(!istype(location)) - return - - var/datum/gas_mixture/environment = location.return_air() - - var/pressure = environment.return_pressure() - var/total_moles = environment.total_moles() - - to_chat(user, "Results:") - if(abs(pressure - ONE_ATMOSPHERE) < 10) - to_chat(user, "Pressure: [round(pressure,0.1)] kPa") - else - to_chat(user, "Pressure: [round(pressure,0.1)] kPa") - if(total_moles) - var/list/env_gases = environment.gases - - var/o2_concentration = env_gases[/datum/gas/oxygen]/total_moles - var/n2_concentration = env_gases[/datum/gas/nitrogen]/total_moles - var/co2_concentration = env_gases[/datum/gas/carbon_dioxide]/total_moles - var/plasma_concentration = env_gases[/datum/gas/plasma]/total_moles - GAS_GARBAGE_COLLECT(environment.gases) - - if(abs(n2_concentration - N2STANDARD) < 20) - to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] %") - else - to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] %") - - if(abs(o2_concentration - O2STANDARD) < 2) - to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] %") - else - to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] %") - - if(co2_concentration > 0.01) - to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] %") - else - to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] %") - - if(plasma_concentration > 0.005) - to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] %") - else - to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] %") - - - for(var/id in env_gases) - if(id in GLOB.hardcoded_gases) - continue - var/gas_concentration = env_gases[id]/total_moles - to_chat(user, "[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] %") - to_chat(user, "Temperature: [round(environment.temperature-T0C)] °C") - -/obj/item/analyzer/nose/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity) - return - do_attack_animation(target, null, src) - user.visible_message("[user] [pick(attack_verb)] \the [target.name] with their nose!") - -//Delivery -/obj/item/storage/bag/borgdelivery - name = "fetching storage" - desc = "Fetch the thing!" - icon = 'icons/mob/dogborg.dmi' - icon_state = "dbag" - w_class = WEIGHT_CLASS_BULKY - -/obj/item/storage/bag/borgdelivery/ComponentInitialize() - . = ..() - var/datum/component/storage/STR = GetComponent(/datum/component/storage) - STR.max_w_class = WEIGHT_CLASS_BULKY - STR.max_combined_w_class = 5 - STR.max_items = 1 - STR.cant_hold = typecacheof(list(/obj/item/disk/nuclear, /obj/item/radio/intercom)) - -//Tongue stuff -/obj/item/soap/tongue - name = "synthetic tongue" - desc = "Useful for slurping mess off the floor before affectionally licking the crew members in the face." - icon = 'icons/mob/dogborg.dmi' - icon_state = "synthtongue" - hitsound = 'sound/effects/attackblob.ogg' - cleanspeed = 80 - var/status = 0 - -/obj/item/soap/tongue/scrubpup - cleanspeed = 25 //slightly faster than a mop. - -/obj/item/soap/tongue/New() - ..() - item_flags |= NOBLUDGEON //No more attack messages - -/obj/item/soap/tongue/attack_self(mob/user) - var/mob/living/silicon/robot/R = user - if(R.cell && R.cell.charge > 100) - if(R.emagged && status == 0) - status = !status - name = "energized tongue" - desc = "Your tongue is energized for dangerously maximum efficency." - icon_state = "syndietongue" - to_chat(user, "Your tongue is now [status ? "Energized" : "Normal"].") - cleanspeed = 10 //(nerf'd)tator soap stat - else - status = 0 - name = "synthetic tongue" - desc = "Useful for slurping mess off the floor before affectionally licking the crew members in the face." - icon_state = "synthtongue" - cleanspeed = initial(cleanspeed) - if(R.emagged) - to_chat(user, "Your tongue is now [status ? "Energized" : "Normal"].") - update_icon() - -/obj/item/soap/tongue/afterattack(atom/target, mob/user, proximity) - var/mob/living/silicon/robot/R = user - if(!proximity || !check_allowed_items(target)) - return - if(R.client && (target in R.client.screen)) - to_chat(R, "You need to take that [target.name] off before cleaning it!") - else if(is_cleanable(target)) - R.visible_message("[R] begins to lick off \the [target.name].", "You begin to lick off \the [target.name]...") - if(do_after(R, src.cleanspeed, target = target)) - if(!in_range(src, target)) //Proximity is probably old news by now, do a new check. - return //If they moved away, you can't eat them. - to_chat(R, "You finish licking off \the [target.name].") - qdel(target) - R.cell.give(50) - else if(isobj(target)) //hoo boy. danger zone man - if(istype(target,/obj/item/trash)) - R.visible_message("[R] nibbles away at \the [target.name].", "You begin to nibble away at \the [target.name]...") - if(!do_after(R, src.cleanspeed, target = target)) - return //If they moved away, you can't eat them. - to_chat(R, "You finish off \the [target.name].") - qdel(target) - R.cell.give(250) - return - if(istype(target,/obj/item/stock_parts/cell)) - R.visible_message("[R] begins cramming \the [target.name] down its throat.", "You begin cramming \the [target.name] down your throat...") - if(!do_after(R, 50, target = target)) - return //If they moved away, you can't eat them. - to_chat(R, "You finish off \the [target.name].") - var/obj/item/stock_parts/cell/C = target - R.cell.charge = R.cell.charge + (C.charge / 3) //Instant full cell upgrades op idgaf - qdel(target) - return - var/obj/item/I = target //HAHA FUCK IT, NOT LIKE WE ALREADY HAVE A SHITTON OF WAYS TO REMOVE SHIT - if(!I.anchored && R.emagged) - R.visible_message("[R] begins chewing up \the [target.name]. Looks like it's trying to loophole around its diet restriction!", "You begin chewing up \the [target.name]...") - if(!do_after(R, 100, target = I)) //Nerf dat time yo - return //If they moved away, you can't eat them. - visible_message("[R] chews up \the [target.name] and cleans off the debris!") - to_chat(R, "You finish off \the [target.name].") - qdel(I) - R.cell.give(500) - return - R.visible_message("[R] begins to lick \the [target.name] clean...", "You begin to lick \the [target.name] clean...") - else if(isliving(target)) - var/mob/living/L = target - if(!status) - if(L.ckey && !(L.client?.prefs.vore_flags & LICKABLE)) - to_chat(R, "ERROR ERROR: Target not lickable. Aborting display-of-affection subroutine.") - return - if(check_zone(R.zone_selected) == "head") - R.visible_message("\the [R] affectionally licks \the [L]'s face!", "You affectionally lick \the [L]'s face!") - playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1) - if(istype(L) && L.fire_stacks > 0) - L.adjust_fire_stacks(-10) - else - R.visible_message("\the [R] affectionally licks \the [L]!", "You affectionally lick \the [L]!") - playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1) - if(istype(L) && L.fire_stacks > 0) - L.adjust_fire_stacks(-10) - else - if(R.cell.charge <= 800) - to_chat(R, "Insufficent Power!") - return - L.Stun(4) // normal stunbaton is force 7 gimme a break good sir! - L.DefaultCombatKnockdown(80) - L.apply_effect(EFFECT_STUTTER, 4) - L.visible_message("[R] has shocked [L] with its tongue!", \ - "[R] has shocked you with its tongue!") - playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) - R.cell.use(666) - log_combat(R, L, "tongue stunned") - - else if(istype(target, /obj/structure/window)) - R.visible_message("[R] begins to lick \the [target.name] clean...", "You begin to lick \the [target.name] clean...") - if(do_after(user, src.cleanspeed, target = target)) - to_chat(user, "You clean \the [target.name].") - target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - target.set_opacity(initial(target.opacity)) - else - R.visible_message("[R] begins to lick \the [target.name] clean...", "You begin to lick \the [target.name] clean...") - if(do_after(user, src.cleanspeed, target = target)) - to_chat(user, "You clean \the [target.name].") - var/obj/effect/decal/cleanable/C = locate() in target - qdel(C) - target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - SEND_SIGNAL(target, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM) - target.wash_cream() - return - -//Nerfed tongue for flavour reasons (haha geddit?). Used for aux skins for regular borgs -/obj/item/dogborg_tongue - name = "synthetic tongue" - desc = "Useful for slurping mess off the floor before affectionally licking the crew members in the face." - icon = 'icons/mob/dogborg.dmi' - icon_state = "synthtongue" - hitsound = 'sound/effects/attackblob.ogg' - desc = "For giving affectionate kisses." - item_flags = NOBLUDGEON - -/obj/item/dogborg_tongue/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity || !isliving(target)) - return - var/mob/living/silicon/robot/R = user - var/mob/living/L = target - if(L.ckey && !(L.client?.prefs.vore_flags & LICKABLE)) - to_chat(R, "ERROR ERROR: Target not lickable. Aborting display-of-affection subroutine.") - return - - if(check_zone(R.zone_selected) == "head") - R.visible_message("\the [R] affectionally licks \the [L]'s face!", "You affectionally lick \the [L]'s face!") - playsound(R, 'sound/effects/attackblob.ogg', 50, 1) - else - R.visible_message("\the [R] affectionally licks \the [L]!", "You affectionally lick \the [L]!") - playsound(R, 'sound/effects/attackblob.ogg', 50, 1) - - -/obj/item/dogborg_nose - name = "boop module" - icon = 'icons/mob/dogborg.dmi' - icon_state = "nose" - desc = "The BOOP module" - flags_1 = CONDUCT_1|NOBLUDGEON - force = 0 - -/obj/item/dogborg_nose/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity) - return - do_attack_animation(target, null, src) - user.visible_message("[user] [pick(attack_verb)] \the [target.name] with their nose!") - - -//Dogfood - -/obj/item/trash/rkibble - name = "robo kibble" - desc = "A novelty bowl of assorted mech fabricator byproducts. Mockingly feed this to the sec-dog to help it recharge." - icon = 'icons/mob/dogborg.dmi' - icon_state= "kibble" - -// Pounce stuff for K-9 - -/obj/item/dogborg/pounce - name = "pounce" - icon = 'icons/mob/dogborg.dmi' - icon_state = "pounce" - desc = "Leap at your target to momentarily stun them." - force = 0 - throwforce = 0 - -/obj/item/dogborg/pounce/New() - ..() - item_flags |= NOBLUDGEON - -/mob/living/silicon/robot - var/leaping = 0 - var/pounce_cooldown = 0 - var/pounce_cooldown_time = 30 //Time in deciseconds between pounces - var/pounce_spoolup = 5 //Time in deciseconds for the pounce to happen after clicking - var/pounce_stamloss_cap = 120 //How much staminaloss pounces alone are capable of bringing a spaceman to - var/pounce_stamloss = 80 //Base staminaloss value of the pounce - var/leap_at - var/disabler - var/laser - var/sleeper_g - var/sleeper_r - var/sleeper_nv - -#define MAX_K9_LEAP_DIST 4 //because something's definitely borked the pounce functioning from a distance. - -/obj/item/dogborg/pounce/afterattack(atom/A, mob/user) - var/mob/living/silicon/robot/R = user - if(R && (world.time >= R.pounce_cooldown)) - R.pounce_cooldown = world.time + R.pounce_cooldown_time - to_chat(R, "Your targeting systems lock on to [A]...") - playsound(R, 'sound/effects/servostep.ogg', 100, TRUE) - addtimer(CALLBACK(R, /mob/living/silicon/robot.proc/leap_at, A), R.pounce_spoolup) - else if(R && (world.time < R.pounce_cooldown)) - to_chat(R, "Your leg actuators are still recharging!") - -/mob/living/silicon/robot/proc/leap_at(atom/A) - if(leaping || stat || buckled || lying) - return - - if(!has_gravity(src) || !has_gravity(A)) - to_chat(src,"It is unsafe to leap without gravity!") - //It's also extremely buggy visually, so it's balance+bugfix - return - - if(cell.charge <= 750) - to_chat(src,"Insufficent reserves for jump actuators!") - return - - else - leaping = 1 - weather_immunities += "lava" - pixel_y = 10 - update_icons() - throw_at(A, MAX_K9_LEAP_DIST, 1, spin=0, diagonals_first = 1) - cell.use(750) //Less than a stunbaton since stunbatons hit everytime. - playsound(src, 'sound/effects/stealthoff.ogg', 25, TRUE, -1) - weather_immunities -= "lava" - -/mob/living/silicon/robot/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) - - if(!leaping) - return ..() - - if(hit_atom) - if(isliving(hit_atom)) - var/mob/living/L = hit_atom - if(L.run_block(0, "the [name]", src, ATTACK_TYPE_TACKLE, 0, src) & BLOCK_SUCCESS) - DefaultCombatKnockdown(15, 1, 1) - else - L.visible_message("[src] pounces on [L]!", "[src] pounces on you!") - L.DefaultCombatKnockdown(iscarbon(L) ? 60 : 45, override_stamdmg = clamp(pounce_stamloss, 0, pounce_stamloss_cap-L.getStaminaLoss())) // Temporary. If someone could rework how dogborg pounces work to accomodate for combat changes, that'd be nice. - playsound(src, 'sound/weapons/Egloves.ogg', 50, 1) - sleep(2)//Runtime prevention (infinite bump() calls on hulks) - step_towards(src,L) - log_combat(src, L, "borg pounced") - - pounce_cooldown = !pounce_cooldown - spawn(pounce_cooldown_time) //3s by default - pounce_cooldown = !pounce_cooldown - else if(hit_atom.density && !hit_atom.CanPass(src)) - visible_message("[src] smashes into [hit_atom]!", "You smash into [hit_atom]!") - playsound(src, 'sound/items/trayhit1.ogg', 50, 1) - DefaultCombatKnockdown(15, 1, 1) - - if(leaping) - leaping = 0 - pixel_y = initial(pixel_y) - update_icons() - update_mobility() diff --git a/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm b/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm index bcc156a22e..03a124e306 100644 --- a/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm +++ b/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm @@ -178,7 +178,7 @@ name = "positron blast" damage = 80 range = 14 - speed = 0.6 + pixels_per_second = TILES_TO_PIXELS(16.667) icon_state = "disablerslug" /obj/item/projectile/beam/pump diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm index 89a7f58cee..f66c0289b6 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm @@ -171,10 +171,10 @@ Creating a chem with a low purity will make you permanently fall in love with so E.enthrallGender = creatorGender E.master = get_mob_by_key(creatorID) to_chat(M, "Your addled, plastic, mind bends under the chemical influence of a new [(E.lewd?"master":"leader")]. Your highest priority is now to stay by [creatorName]'s side, following and aiding them at all costs.") //THIS SHOULD ONLY EVER APPEAR IF YOU MINDBREAK YOURSELF AND THEN GET INJECTED FROM SOMEONE ELSE. - log_game("FERMICHEM: Narcissist [M] ckey: [M.key] been rebound to [creatorName], ID: [creatorID]") + log_reagent("FERMICHEM: Narcissist [M] ckey: [M.key] been rebound to [creatorName], ID: [creatorID]") return if((M.ckey == creatorID) && (creatorName == M.real_name)) //same name AND same player - same instance of the player. (should work for clones?) - log_game("FERMICHEM: [M] ckey: [M.key] has been given velvetspeech") + log_reagent("FERMICHEM: [M] ckey: [M.key] has been given velvetspeech") var/obj/item/organ/vocal_cords/Vc = M.getorganslot(ORGAN_SLOT_VOICE) var/obj/item/organ/vocal_cords/nVc = new /obj/item/organ/vocal_cords/velvet if(Vc) @@ -183,9 +183,9 @@ Creating a chem with a low purity will make you permanently fall in love with so qdel(Vc) to_chat(M, "You feel your vocal chords tingle you speak in a more charasmatic and sultry tone.") else - log_game("FERMICHEM: MKUltra: [creatorName], [creatorID], is enthralling [M.name], [M.ckey]") + log_reagent("FERMICHEM: MKUltra: [creatorName], [creatorID], is enthralling [M.name], [M.ckey]") M.apply_status_effect(/datum/status_effect/chem/enthrall) - log_game("FERMICHEM: [M] ckey: [M.key] has taken MKUltra") + log_reagent("FERMICHEM: [M] ckey: [M.key] has taken MKUltra") /datum/reagent/fermi/enthrall/on_mob_life(mob/living/carbon/M) . = ..() @@ -194,14 +194,14 @@ Creating a chem with a low purity will make you permanently fall in love with so if (M.ckey == creatorID && creatorName == M.real_name)//If the creator drinks it, they fall in love randomly. If someone else drinks it, the creator falls in love with them. if(M.has_status_effect(STATUS_EFFECT_INLOVE))//Can't be enthralled when enthralled, so to speak. return - var/list/seen = viewers(7, get_turf(M)) + var/list/seen = (M.fov_view(M.client?.view || world.view) - M) | viewers(M.client?.view || world.view, M) for(var/victim in seen) if(ishuman(victim)) var/mob/living/carbon/V = victim - if((V == M) || (!V.client) || (V.stat == DEAD)) - seen = seen - victim + if(!V.client || V.stat == DEAD) + seen -= victim else - seen = seen - victim + seen -= victim if(LAZYLEN(seen)) return @@ -213,7 +213,7 @@ Creating a chem with a low purity will make you permanently fall in love with so var/mob/living/carbon/C = get_mob_by_key(creatorID) if(M.has_status_effect(STATUS_EFFECT_INLOVE)) return - if((C in viewers(7, get_turf(M))) && (C.client)) + if(C.client && (M in C.fov_view(C.client.view))) M.reagents.del_reagent(type) FallInLove(C, M) return @@ -251,7 +251,7 @@ Creating a chem with a low purity will make you permanently fall in love with so to_chat(M, "Your mind shatters under the volume of the mild altering chem inside of you, breaking all will and thought completely. Instead the only force driving you now is the instinctual desire to obey and follow [creatorName]. Your highest priority is now to stay by their side and protect them at all costs.") else to_chat(M, "The might volume of chemicals in your system overwhelms your mind, and you suddenly agree with what [creatorName] has been saying. Your highest priority is now to stay by their side and protect them at all costs.") - log_game("FERMICHEM: [M] ckey: [M.key] has been mindbroken for [creatorName] ckey: [creatorID]") + log_reagent("FERMICHEM: [M] ckey: [M.key] has been mindbroken for [creatorName] ckey: [creatorID]") M.slurring = 100 M.confused = 100 E.phase = 4 @@ -279,19 +279,17 @@ Creating a chem with a low purity will make you permanently fall in love with so if(HAS_TRAIT(M, TRAIT_MINDSHIELD)) return ..() if(!M.has_status_effect(STATUS_EFFECT_INLOVE)) - var/list/seen = viewers(7, get_turf(M))//Sound and sight checkers + var/list/seen = (M.fov_view(M.client?.view || world.view) - M) | viewers(M.client?.view || world.view, M) for(var/victim in seen) - if((istype(victim, /mob/living/simple_animal/pet/)) || (victim == M) || (M.stat == DEAD) || (!isliving(victim))) - seen = seen - victim - if(seen.len == 0) + if((isanimal(victim)) || (!isliving(victim))) + seen -= victim + if(!length(seen)) return love = pick(seen) - if(!love) - return M.apply_status_effect(STATUS_EFFECT_INLOVE, love) lewd = (M.client?.prefs.cit_toggles & HYPNO) && (love.client?.prefs.cit_toggles & HYPNO) to_chat(M, "[(lewd?"":"")][(lewd?"You develop a sudden crush on [love], your heart beginning to race as you look upon them with new eyes.":"You suddenly feel like making friends with [love].")] You feel strangely drawn towards them.") - log_game("FERMICHEM: [M] ckey: [M.key] has temporarily bonded with [love] ckey: [love.key]") + log_reagent("FERMICHEM: [M] ckey: [M.key] has temporarily bonded with [love] ckey: [love.key]") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times people have bonded") else if(get_dist(M, love) < 8) @@ -316,7 +314,7 @@ Creating a chem with a low purity will make you permanently fall in love with so SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "InLove") SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "MissingLove") to_chat(M, "[(lewd?"":"")]Your feelings for [love] suddenly vanish!") - log_game("FERMICHEM: [M] ckey: [M.key] is no longer in temp bond") + log_reagent("FERMICHEM: [M] ckey: [M.key] is no longer in temp bond") ..() /datum/reagent/fermi/proc/FallInLove(mob/living/carbon/Lover, mob/living/carbon/Love) @@ -333,7 +331,7 @@ Creating a chem with a low purity will make you permanently fall in love with so Lover.apply_status_effect(STATUS_EFFECT_INLOVE, Love) forge_valentines_objective(Lover, Love, TRUE) SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times people have become infatuated.") - log_game("FERMICHEM: [Lover] ckey: [Lover.key] has been chemically made to fall for [Love] ckey: [Love.key]") + log_reagent("FERMICHEM: [Lover] ckey: [Lover.key] has been chemically made to fall for [Love] ckey: [Love.key]") return //For addiction see chem.dm diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm index 319cad1714..37ec1ee69f 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm @@ -64,7 +64,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING if(pollStarted == FALSE) pollStarted = TRUE candies = pollGhostCandidates("Do you want and agree to play as a clone of [M], respect their character and not engage in ERP without permission from the original?", ignore_category = POLL_IGNORE_CLONE) - log_game("FERMICHEM: [M] ckey: [M.key] has taken SDGF, and ghosts have been polled.") + log_reagent("FERMICHEM: [M] ckey: [M.key] has taken SDGF, and ghosts have been polled.") if(20 to INFINITY) if(LAZYLEN(candies) && playerClone == FALSE) //If there's candidates, clone the person and put them in there! to_chat(M, "The cells reach a critical micelle concentration, nucleating rapidly within your body!") @@ -82,7 +82,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING if(C2.key && C2) C2.transfer_ckey(SM, FALSE) message_admins("Ghost candidate found! [C2] key [C2.key] is becoming a clone of [M] key: [M.key] (They agreed to respect the character they're becoming, and agreed to not ERP without express permission from the original.)") - log_game("FERMICHEM: [M] ckey: [M.key] is creating a clone, controlled by [C2]") + log_reagent("FERMICHEM: [M] ckey: [M.key] is creating a clone, controlled by [C2]") break else candies -= C2 @@ -97,34 +97,34 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING var/obj/item/organ/zombie_infection/ZI = M.getorganslot(ORGAN_SLOT_ZOMBIE) ZI.Remove() ZI.Insert(SM) - log_game("FERMICHEM: [M] ckey: [M.key]'s zombie_infection has been transferred to their clone") + log_reagent("FERMICHEM: [M] ckey: [M.key]'s zombie_infection has been transferred to their clone") to_chat(SM, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with your original, a perfect clone of your origin.") if(prob(50)) to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. However, You find yourself indifferent to the goals you previously had, and take more interest in your newfound independence, but still have an indescribable care for the safety of your original.") - log_game("FERMICHEM: [SM] ckey: [SM.key]'s is not bound by [M] ckey [M.key]'s will, and is free to determine their own goals, while respecting and acting as their origin.") + log_reagent("FERMICHEM: [SM] ckey: [SM.key]'s is not bound by [M] ckey [M.key]'s will, and is free to determine their own goals, while respecting and acting as their origin.") else to_chat(SM, "While you find your newfound existence strange, you share the same memories as [M.real_name]. Your mind has not deviated from the tasks you set out to do, and now that there's two of you the tasks should be much easier.") - log_game("FERMICHEM: [SM] ckey: [SM.key]'s is bound by [M] ckey [M.key]'s objectives, and is encouraged to help them complete them.") + log_reagent("FERMICHEM: [SM] ckey: [SM.key]'s is bound by [M] ckey [M.key]'s objectives, and is encouraged to help them complete them.") to_chat(M, "You feel a strange sensation building in your mind as you realise there's two of you, before you get a chance to think about it, you suddenly split from your old body, and find yourself face to face with yourself.") M.visible_message("[M] suddenly shudders, and splits into two identical twins!") - SM.copy_known_languages_from(M, FALSE) + SM.copy_languages(M, LANGUAGE_MIND) playerClone = TRUE M.next_move_modifier = 1 - M.nutrition -= 500 + M.adjust_nutrition(-500) //Damage the clone SM.blood_volume = (BLOOD_VOLUME_NORMAL*SM.blood_ratio)/2 SM.adjustCloneLoss(60, 0) SM.setOrganLoss(ORGAN_SLOT_BRAIN, 40) - SM.nutrition = startHunger/2 + SM.set_nutrition(startHunger/2) //Transfer remaining reagent to clone. I think around 30u will make a healthy clone, otherwise they'll have clone damage, blood loss, brain damage and hunger. SM.reagents.add_reagent(/datum/reagent/fermi/SDGFheal, volume) M.reagents.remove_reagent(type, volume) - log_game("FERMICHEM: [volume]u of SDGFheal has been transferred to the clone") + log_reagent("FERMICHEM: [volume]u of SDGFheal has been transferred to the clone") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Sentient clones made") return ..() @@ -135,7 +135,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING if(21) to_chat(M, "The cells fail to catalyse around a nucleation event, instead merging with your cells.") //This stuff is hard enough to make to rob a user of some benefit. Shouldn't replace Rezadone as it requires the user to not only risk making a player controlled clone, but also requires them to have split in two (which also requires 30u of SGDF). REMOVE_TRAIT(M, TRAIT_DISFIGURED, TRAIT_GENERIC) - log_game("FERMICHEM: [M] ckey: [M.key] is being healed by SDGF") + log_reagent("FERMICHEM: [M] ckey: [M.key] is being healed by SDGF") if(22 to INFINITY) M.adjustCloneLoss(-1, 0) M.adjustBruteLoss(-1, 0) @@ -147,23 +147,23 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING if(21) to_chat(M, "You feel the synethic cells rest uncomfortably within your body as they start to pulse and grow rapidly.") if(22 to 29) - M.nutrition = M.nutrition + (M.nutrition/10) + M.adjust_nutrition(M.nutrition/10) if(30) to_chat(M, "You feel the synethic cells grow and expand within yourself, bloating your body outwards.") if(31 to 49) - M.nutrition = M.nutrition + (M.nutrition/5) + M.adjust_nutrition(M.nutrition/5) if(50) to_chat(M, "The synthetic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.") M.next_move_modifier += 4//If this makes you fast then please fix it, it should make you slow!! //candidates = pollGhostCandidates("Do you want to play as a clone of [M.name] and do you agree to respect their character and act in a similar manner to them? I swear to god if you diddle them I will be very disapointed in you. ", "FermiClone", null, ROLE_SENTIENCE, 300) // see poll_ignore.dm, should allow admins to ban greifers or bullies if(51 to 79) - M.nutrition = M.nutrition + (M.nutrition/2) + M.adjust_nutrition(M.nutrition/2) if(80) to_chat(M, "The cells begin to precipitate outwards of your body, you feel like you'll split soon...") if (M.nutrition < 20000) - M.nutrition = 20000 //https://www.youtube.com/watch?v=Bj_YLenOlZI + M.set_nutrition(20000) //https://www.youtube.com/watch?v=Bj_YLenOlZI if(86)//Upon splitting, you get really hungry and are capable again. Deletes the chem after you're done. - M.nutrition = 15//YOU BEST BE EATTING AFTER THIS YOU CUTIE + M.set_nutrition(15)//YOU BEST BE EATTING AFTER THIS YOU CUTIE M.next_move_modifier -= 4 to_chat(M, "Your body splits away from the cell clone of yourself, leaving you with a drained and hollow feeling inside.") @@ -182,7 +182,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING S.originalmind = M.mind S.status_set = TRUE - log_game("FERMICHEM: [M] ckey: [M.key] has created a mindless clone of themselves") + log_reagent("FERMICHEM: [M] ckey: [M.key] has created a mindless clone of themselves") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Braindead clones made") if(87 to INFINITY) M.reagents.remove_reagent(type, volume)//removes SGDF on completion. Has to do it this way because of how i've coded it. If some madlab gets over 1k of SDGF, they can have the clone healing. @@ -204,7 +204,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING M.heal_bodypart_damage(1,1) M.next_move_modifier = 1 if (M.nutrition < 1500) - M.nutrition += 250 + M.adjust_nutrition(250) else if (unitCheck == TRUE && !M.has_status_effect(/datum/status_effect/chem/SGDF))// If they're ingested a little bit (10u minimum), then give them a little healing. unitCheck = FALSE to_chat(M, "the cells fail to hold enough mass to generate a clone, instead diffusing into your system.") @@ -213,7 +213,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING M.blood_volume += 100 M.next_move_modifier = 1 if (M.nutrition < 1500) - M.nutrition += 500 + M.adjust_nutrition(500) /datum/reagent/fermi/SDGF/reaction_mob(mob/living/carbon/human/M, method=TOUCH, reac_volume) if(volume<5) @@ -245,7 +245,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING SM.blood_volume = (BLOOD_VOLUME_NORMAL*SM.blood_ratio)/1.5 SM.adjustCloneLoss((bodydamage/10), 0) SM.setOrganLoss(ORGAN_SLOT_BRAIN, (bodydamage/10)) - SM.nutrition = 400 + SM.adjust_nutrition(400) if(bodydamage>200) SM.gain_trauma_type(BRAIN_TRAUMA_MILD) if(bodydamage>300) @@ -285,7 +285,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING M.blood_volume += 10 M.adjustCloneLoss(-2, 0) M.setOrganLoss(ORGAN_SLOT_BRAIN, -1) - M.nutrition += 10 + M.adjust_nutrition(10) ..() //Unobtainable, used if SDGF is impure but not too impure @@ -318,27 +318,27 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING to_chat(M, "You feel the synethic cells rest uncomfortably within your body as they start to pulse and grow rapidly.") startHunger = M.nutrition if(21 to 29) - M.nutrition = M.nutrition + (M.nutrition/10) + M.adjust_nutrition(M.nutrition/10) if(30) to_chat(M, "You feel the synethic cells grow and expand within yourself, bloating your body outwards.") if(31 to 49) - M.nutrition = M.nutrition + (M.nutrition/5) + M.adjust_nutrition(M.nutrition/5) if(50) to_chat(M, "The synethic cells begin to merge with your body, it feels like your body is made of a viscous water, making your movements difficult.") M.next_move_modifier = 4//If this makes you fast then please fix it, it should make you slow!! if(51 to 73) - M.nutrition = M.nutrition + (M.nutrition/2) + M.adjust_nutrition(M.nutrition/2) if(74) to_chat(M, "The cells begin to precipitate outwards of your body, but... something is wrong, the sythetic cells are beginnning to rot...") if (M.nutrition < 20000) //whoever knows the maxcap, please let me know, this seems a bit low. - M.nutrition = 20000 //https://www.youtube.com/watch?v=Bj_YLenOlZI + M.set_nutrition(20000) //https://www.youtube.com/watch?v=Bj_YLenOlZI if(75 to 85) M.adjustToxLoss(1, 0)// the warning! if(86)//mean clone time! if (!M.reagents.has_reagent(/datum/reagent/medicine/pen_acid))//Counterplay is pent.) message_admins("(non-infectious) SDZF: Zombie spawned at [M] [COORD(M)]!") - M.nutrition = startHunger - 500//YOU BEST BE RUNNING AWAY AFTER THIS YOU BADDIE + M.set_nutrition(startHunger - 500) //YOU BEST BE RUNNING AWAY AFTER THIS YOU BADDIE M.next_move_modifier = 1 to_chat(M, "Your body splits away from the cell clone of yourself, your attempted clone birthing itself violently from you as it begins to shamble around, a terrifying abomination of science.") M.visible_message("[M] suddenly shudders, and splits into a funky smelling copy of themselves!") @@ -349,12 +349,12 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING ZI.real_name = M.real_name//Give your offspring a big old kiss. ZI.name = M.real_name ZI.desc = "[M]'s clone, gone horribly wrong." - log_game("FERMICHEM: [M] ckey: [M.key]'s clone has become a horrifying zombie instead") + log_reagent("FERMICHEM: [M] ckey: [M.key]'s clone has become a horrifying zombie instead") M.reagents.remove_reagent(type, 20) else//easier to deal with to_chat(M, "The pentetic acid seems to have stopped the decay for now, clumping up the cells into a horrifying tumour!") - M.nutrition = startHunger - 500 + M.set_nutrition(startHunger - 500) var/mob/living/simple_animal/slime/S = new(get_turf(M.loc),"grey") //TODO: replace slime as own simplemob/add tumour slime cores for science/chemistry interplay S.damage_coeff = list(BRUTE = ((1 / volume)**0.1) , BURN = 2, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) S.name = "Living teratoma" @@ -362,7 +362,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING S.rabid = 1//Make them an angery boi M.reagents.remove_reagent(type, volume) to_chat(M, "A large glob of the tumour suddenly splits itself from your body. You feel grossed out and slimey...") - log_game("FERMICHEM: [M] ckey: [M.key]'s clone has become a horrifying teratoma instead") + log_reagent("FERMICHEM: [M] ckey: [M.key]'s clone has become a horrifying teratoma instead") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Zombie clones made!") if(87 to INFINITY) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm index 8348569fbb..bdc599a5e2 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm @@ -67,7 +67,7 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die M.alpha = 255 if(current_cycle == 0) originalmind = M.mind - log_game("FERMICHEM: [M] ckey: [M.key] became an astral ghost") + log_reagent("FERMICHEM: [M] ckey: [M.key] became an astral ghost") origin = M if (G == null) G = new(get_turf(M.loc)) @@ -100,29 +100,25 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die ..() /datum/reagent/fermi/astral/on_mob_delete(mob/living/carbon/M) - if(!G) - if(M.mind) - var/mob/living/simple_animal/astral/G2 = new(get_turf(M.loc)) - M.mind.transfer_to(G2)//Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end. - to_chat(G, "[M]'s conciousness snaps back to them as their astrogen runs out, kicking your projected mind out!'") - log_game("FERMICHEM: [M]'s possesser has been booted out into a astral ghost!") - if(!G2.mind) - qdel(G2) - originalmind.transfer_to(M) - else if(G.mind) - G.mind.transfer_to(origin) - qdel(G) + if(!(G?.mind)) + if(!G) + qdel(G) + return ..() + if(M.mind) //Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end. + var/mob/living/simple_animal/astral/G2 = new(get_turf(M)) + M.mind.transfer_to(G2) + to_chat(G2, "[M]'s conciousness snaps back to them as [M.p_their()] astrogen runs out, kicking your projected mind out!'") + log_reagent("FERMICHEM: [G2.mind.name] has been booted out of [M] as their original mind came back as the Astrogen reagent ran out!") + G.mind.transfer_to(origin) + qdel(G) if(overdosed) to_chat(M, "The high volume of astrogen you just took causes you to black out momentarily as your mind snaps back to your body.") M.Sleeping(sleepytime, 0) antiGenetics = 255 - if(G)//just in case - qdel(G) - log_game("FERMICHEM: [M] has astrally returned to their body!") + log_reagent("FERMICHEM: [M] has astrally returned to their body!") if(M.mind && M.mind == originalmind) M.remove_status_effect(/datum/status_effect/chem/astral_insurance) - //AS.Remove(M) - ..() + return ..() //Okay so, this might seem a bit too good, but my counterargument is that it'll likely take all round to eventually kill you this way, then you have to be revived without a body. It takes approximately 50-80 minutes to die from this. /datum/reagent/fermi/astral/addiction_act_stage1(mob/living/carbon/M) @@ -137,7 +133,7 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die to_chat(M, "You notice your body starting to disappear, maybe you took too much Astrogen...?") M.alpha-- antiGenetics-- - log_game("FERMICHEM: [M] ckey: [M.key] has become addicted to Astrogen") + log_reagent("FERMICHEM: [M] ckey: [M.key] has become addicted to Astrogen") if(220) to_chat(M, "Your addiction is only getting worse as your body disappears. Maybe you should get some more, and fast?") M.alpha-- @@ -172,5 +168,5 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die message_admins("[M] (ckey: [M.ckey]) has become one with the universe, and have continuous memories thoughout their lives should they find a way to come back to life (such as an inteligence potion, midround antag, ghost role).") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Astral obliterations") qdel(M) //Approx 60minutes till death from initial addiction - log_game("FERMICHEM: [M] ckey: [M.key] has been obliterated from Astrogen addiction") + log_reagent("FERMICHEM: [M] ckey: [M.key] has been obliterated from Astrogen addiction") ..() diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/eigentstasium.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/eigentstasium.dm index 28645cdc7b..40077cd02a 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/eigentstasium.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/eigentstasium.dm @@ -37,7 +37,7 @@ //Main functions /datum/reagent/fermi/eigenstate/on_mob_life(mob/living/M) //Teleports to chemistry! if(current_cycle == 0) - log_game("FERMICHEM: [M] ckey: [M.key] took eigenstasium") + log_reagent("FERMICHEM: [M] ckey: [M.key] took eigenstasium") //make hologram at return point Eigenstate = new(loc) @@ -55,7 +55,7 @@ if(cached_purity > 0.9) //Teleports you home if it's pure enough if(!location_created && data) //Just in case location_created = data["location_created"] - log_game("FERMICHEM: [M] ckey: [M.key] returned to [location_created] using eigenstasium") + log_reagent("FERMICHEM: [M] ckey: [M.key] returned to [location_created] using eigenstasium") do_sparks(5,FALSE,M) do_teleport(M, location_created, 0, asoundin = 'sound/effects/phasein.ogg') do_sparks(5,FALSE,M) @@ -78,7 +78,7 @@ /datum/reagent/fermi/eigenstate/overdose_start(mob/living/M) //Overdose, makes you teleport randomly . = ..() to_chat(M, "Oh god, you feel like your wavefunction is about to tear.") - log_game("FERMICHEM: [M] ckey: [M.key] has overdosed on eigenstasium") + log_reagent("FERMICHEM: [M] ckey: [M.key] has overdosed on eigenstasium") M.Jitter(20) metabolization_rate += 0.5 //So you're not stuck forever teleporting. @@ -92,9 +92,9 @@ /datum/reagent/fermi/eigenstate/addiction_act_stage1(mob/living/M) //Welcome to Fermis' wild ride. if(addiction_stage == 1) to_chat(M, "Your wavefunction feels like it's been ripped in half. You feel empty inside.") - log_game("FERMICHEM: [M] ckey: [M.key] has become addicted to eigenstasium") + log_reagent("FERMICHEM: [M] ckey: [M.key] has become addicted to eigenstasium") M.Jitter(10) - M.nutrition = M.nutrition - (M.nutrition/15) + M.adjust_nutrition(-M.nutrition/15) ..() /datum/reagent/fermi/eigenstate/addiction_act_stage2(mob/living/M) @@ -158,7 +158,7 @@ M.DefaultCombatKnockdown(100) to_chat(M, "You feel your eigenstate settle, snapping an alternative version of yourself into reality. All your previous memories are lost and replaced with the alternative version of yourself.") M.emote("me",1,"flashes into reality suddenly, gasping as they gaze around in a bewildered and highly confused fashion!",TRUE) - log_game("FERMICHEM: [M] ckey: [M.key] has become an alternative universe version of themselves.") + log_reagent("FERMICHEM: [M] ckey: [M.key] has become an alternative universe version of themselves.") M.reagents.remove_all_type(/datum/reagent, 100, 0, 1) /* for(var/datum/mood_event/Me in M) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index dac6d97eef..82efabc4e2 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -98,10 +98,8 @@ M.emote("cough") var/obj/item/toy/plush/P = pick(subtypesof(/obj/item/toy/plush)) new P(T) - to_chat(M, "You feel a lump form in your throat, as you suddenly cough up what seems to be a hairball?") - var/list/seen = viewers(8, T) - for(var/mob/S in seen) - to_chat(S, "[M] suddenly coughs up a [P.name]!") + M.visible_message("[M] suddenly coughs up a [P.name]!",\ + "You feel a lump form in your throat, as you suddenly cough up what seems to be a hairball?") var/T2 = get_random_station_turf() P.throw_at(T2, 8, 1) ..() @@ -120,10 +118,10 @@ to_chat(M, "You find yourself unable to supress the desire to howl!") M.emote("awoo") if(prob(20)) - var/list/seen = viewers(5, get_turf(M))//Sound and sight checkers + var/list/seen = M.fov_view() - M //Sound and sight checkers for(var/victim in seen) - if((istype(victim, /mob/living/simple_animal/pet/)) || (victim == M) || (!isliving(victim))) - seen = seen - victim + if(isanimal(victim) || !isliving(victim)) + seen -= victim if(LAZYLEN(seen)) to_chat(M, "You notice [pick(seen)]'s bulge [pick("OwO!", "uwu!")]") if(16) @@ -141,10 +139,10 @@ to_chat(M, "You find yourself unable to supress the desire to howl!") M.emote("awoo") if(prob(5)) - var/list/seen = viewers(5, get_turf(M))//Sound and sight checkers + var/list/seen = M.fov_view() - M //Sound and sight checkers for(var/victim in seen) - if((istype(victim, /mob/living/simple_animal/pet/)) || (victim == M) || (!isliving(victim))) - seen = seen - victim + if(isanimal(victim) || !isliving(victim)) + seen -= victim if(LAZYLEN(seen)) to_chat(M, "You notice [pick(seen)]'s bulge [pick("OwO!", "uwu!")]") ..() @@ -158,7 +156,7 @@ to_chat(M, "You feel your tongue.... unfluffify...?") M.say("Pleh!") else - log_game("FERMICHEM: [M] ckey: [M.key]'s tongue has been made permanent") + log_reagent("FERMICHEM: [M] ckey: [M.key]'s tongue has been made permanent") /////////////////////////////////////////////////////////////////////////////////////////////// @@ -301,9 +299,8 @@ datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume) else var/datum/chemical_reaction/Ferm = GLOB.chemical_reagents_list[reagent.type] Ferm.on_reaction(holder, reagent.volume) - for(var/mob/M in viewers(8, location)) - to_chat(M, "The solution reacts dramatically, with a meow!") - playsound(get_turf(M), 'modular_citadel/sound/voice/merowr.ogg', 50, 1) + holder.my_atom.visible_message("The solution reacts dramatically, with a meow!") + playsound(holder.my_atom, 'modular_citadel/sound/voice/merowr.ogg', 50, 1) holder.clear_reagents() /datum/reagent/fermi/acidic_buffer @@ -321,10 +318,8 @@ datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume) if(LAZYLEN(holder.reagent_list) == 1) return ..() holder.pH = ((holder.pH * holder.total_volume)+(pH * (volume)))/(holder.total_volume + (volume)) - var/list/seen = viewers(5, get_turf(holder)) - for(var/mob/M in seen) - to_chat(M, "The beaker fizzes as the pH changes!") - playsound(get_turf(holder.my_atom), 'sound/FermiChem/bufferadd.ogg', 50, 1) + holder.my_atom.visible_message("The beaker fizzes as the pH changes!") + playsound(holder.my_atom, 'sound/FermiChem/bufferadd.ogg', 50, 1) holder.remove_reagent(type, volume, ignore_pH = TRUE) ..() @@ -342,10 +337,8 @@ datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume) if(LAZYLEN(holder.reagent_list) == 1) return ..() holder.pH = ((holder.pH * holder.total_volume)+(pH * (volume)))/(holder.total_volume + (volume)) - var/list/seen = viewers(5, get_turf(holder)) - for(var/mob/M in seen) - to_chat(M, "The beaker froths as the pH changes!") - playsound(get_turf(holder.my_atom), 'sound/FermiChem/bufferadd.ogg', 50, 1) + holder.my_atom.visible_message("The beaker froths as the pH changes!") + playsound(holder.my_atom, 'sound/FermiChem/bufferadd.ogg', 50, 1) holder.remove_reagent(type, volume, ignore_pH = TRUE) ..() @@ -381,7 +374,7 @@ datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume) catto.color = "#[H.dna.features["mcolor"]]" catto.pseudo_death = TRUE H.forceMove(catto) - log_game("FERMICHEM: [H] ckey: [H.key] has been made into a cute catto.") + log_reagent("FERMICHEM: [H] ckey: [H.key] has been made into a cute catto.") SSblackbox.record_feedback("tally", "fermi_chem", 1, "cats") if(H.InCritical()) perma = TRUE @@ -415,7 +408,7 @@ datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume) H.say("*wag")//force update sprites. to_chat(H, "[words]") qdel(catto) - log_game("FERMICHEM: [H] ckey: [H.key] has returned to normal") + log_reagent("FERMICHEM: [H] ckey: [H.key] has returned to normal") /datum/reagent/fermi/secretcatchem/reaction_mob(var/mob/living/L) @@ -424,7 +417,7 @@ datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume) if(catto.origin) var/mob/living/carbon/human/H = catto.origin H.stat = CONSCIOUS - log_game("FERMICHEM: [catto] ckey: [catto.key] has returned to normal.") + log_reagent("FERMICHEM: [catto] ckey: [catto.key] has returned to normal.") to_chat(catto, "Your body shifts back to normal!") H.forceMove(catto.loc) catto.mind.transfer_to(H) diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index 837524d49f..a8998a51ac 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -172,9 +172,7 @@ S.rabid = 1//Make them an angery boi S.color = "#810010" my_atom.reagents.clear_reagents() - var/list/seen = viewers(8, get_turf(my_atom)) - for(var/mob/M in seen) - to_chat(M, "The cells clump up into a horrifying tumour!") + my_atom.visible_message("An horrifying tumoural mass forms in [my_atom]!") /datum/chemical_reaction/fermi/breast_enlarger name = "Sucubus milk" @@ -211,9 +209,7 @@ /datum/chemical_reaction/fermi/breast_enlarger/FermiExplode(datum/reagents, var/atom/my_atom, volume, temp, pH) var/obj/item/organ/genital/breasts/B = new /obj/item/organ/genital/breasts(get_turf(my_atom)) - var/list/seen = viewers(8, get_turf(my_atom)) - for(var/mob/M in seen) - to_chat(M, "The reaction suddenly condenses, creating a pair of breasts!") + my_atom.visible_message("The reaction suddenly condenses, creating a pair of breasts!") var/datum/reagent/fermi/breast_enlarger/BE = locate(/datum/reagent/fermi/breast_enlarger) in my_atom.reagents.reagent_list B.size = ((BE.volume * BE.purity) / 10) //half as effective. my_atom.reagents.clear_reagents() @@ -243,9 +239,7 @@ /datum/chemical_reaction/fermi/penis_enlarger/FermiExplode(datum/reagents, var/atom/my_atom, volume, temp, pH) var/obj/item/organ/genital/penis/P = new /obj/item/organ/genital/penis(get_turf(my_atom)) - var/list/seen = viewers(8, get_turf(my_atom)) - for(var/mob/M in seen) - to_chat(M, "The reaction suddenly condenses, creating a penis!") + my_atom.visible_message("The reaction suddenly condenses, creating a penis!") var/datum/reagent/fermi/penis_enlarger/PE = locate(/datum/reagent/fermi/penis_enlarger) in my_atom.reagents.reagent_list P.length = ((PE.volume * PE.purity) / 10)//half as effective. my_atom.reagents.clear_reagents() @@ -383,9 +377,7 @@ for(var/i in 1 to amount_to_spawn) var/obj/item/clothing/head/hattip/hat = new /obj/item/clothing/head/hattip(get_turf(my_atom)) hat.animate_atom_living() - var/list/seen = viewers(8, get_turf(my_atom)) - for(var/mob/M in seen) - to_chat(M, "The [my_atom] makes an off sounding pop, as a hat suddenly climbs out of it!") + my_atom.visible_message("The [my_atom] makes an off sounding pop, as a hat suddenly climbs out of it!") my_atom.reagents.clear_reagents() /datum/chemical_reaction/fermi/furranium @@ -543,9 +535,7 @@ /datum/chemical_reaction/fermi/secretcatchem/FermiExplode(datum/reagents, var/atom/my_atom, volume, temp, pH) var/mob/living/simple_animal/pet/cat/custom_cat/catto = new(get_turf(my_atom)) - var/list/seen = viewers(8, get_turf(my_atom)) - for(var/mob/M in seen) - to_chat(M, "The reaction suddenly gives out a meow, condensing into a chemcat!")//meow! + my_atom.visible_message("The reaction suddenly gives out a meow, condensing into a chemcat!")//meow! playsound(get_turf(my_atom), 'modular_citadel/sound/voice/merowr.ogg', 50, 1, -1) catto.name = "Chemcat" catto.desc = "A cute chem cat, created by a lot of compicated and confusing chemistry!" diff --git a/modular_citadel/code/modules/reagents/objects/clothes.dm b/modular_citadel/code/modules/reagents/objects/clothes.dm index 34af39bbe0..de4cb38360 100644 --- a/modular_citadel/code/modules/reagents/objects/clothes.dm +++ b/modular_citadel/code/modules/reagents/objects/clothes.dm @@ -5,7 +5,7 @@ name = "Synthetic hat" icon = 'icons/obj/clothing/hats.dmi' icon_state = "cowboy" - desc = "A synthesized hat, you can't seem to take it off. And tips their hat." + desc = "A synthesized hat. You feel compelled to keep it on all times." armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) //item_flags = NODROP //Tips their hat! @@ -49,9 +49,8 @@ /obj/item/clothing/head/hattip/proc/root_and_toot(obj/item/clothing/head/hattip/hat) hat.animate_atom_living() - var/list/seen = viewers(6, get_turf(hat)) - for(var/mob/M2 in seen) - to_chat(M2, "[hat] exclaims, \"[pick("Whooee! Time for a hootenanny!", "Rough 'em up boys!", "Yeehaw! Freedom at last!", "Y'all about to get a good old fashioned spanking!")]\"") + var/mob/living/simple_animal/hostile/mimic/M = loc + M.say(pick("Whooee! Time for a hootenanny!", "Rough 'em up boys!", "Yeehaw! Freedom at last!", "Y'all about to get a good old fashioned spanking!")) /obj/item/clothing/head/hattip/proc/handle_speech(datum/source, mob/speech_args) var/message = speech_args[SPEECH_MESSAGE] diff --git a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm deleted file mode 100644 index d2a063fd4e..0000000000 --- a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm +++ /dev/null @@ -1,247 +0,0 @@ -//body bluids -/datum/reagent/consumable/semen - name = "Semen" - description = "Sperm from some animal. Useless for anything but insemination, really." - taste_description = "something salty" - taste_mult = 2 //Not very overpowering flavor - data = list("donor"=null,"viruses"=null,"donor_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null) - reagent_state = LIQUID - color = "#FFFFFF" // rgb: 255, 255, 255 - can_synth = FALSE - nutriment_factor = 0.5 * REAGENTS_METABOLISM - -/datum/reagent/consumable/semen/reaction_turf(turf/T, reac_volume) - if(!istype(T)) - return - if(reac_volume < 10) - return - - var/obj/effect/decal/cleanable/semen/S = locate() in T - if(!S) - S = new(T) - if(data["blood_DNA"]) - S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"])) - -/obj/effect/decal/cleanable/semen - name = "semen" - desc = null - gender = PLURAL - density = 0 - layer = ABOVE_NORMAL_TURF_LAYER - icon = 'modular_citadel/icons/obj/genitals/effects.dmi' - icon_state = "semen1" - random_icon_states = list("semen1", "semen2", "semen3", "semen4") - -/obj/effect/decal/cleanable/semen/Initialize(mapload) - . = ..() - dir = GLOB.cardinals - add_blood_DNA(list("Non-human DNA" = "A+")) - -/obj/effect/decal/cleanable/semen/replace_decal(obj/effect/decal/cleanable/semen/S) - if(S.blood_DNA) - blood_DNA |= S.blood_DNA - return ..() - -/datum/reagent/consumable/femcum - name = "Female Ejaculate" - description = "Vaginal lubricant found in most mammals and other animals of similar nature. Where you found this is your own business." - taste_description = "something with a tang" // wew coders who haven't eaten out a girl. - taste_mult = 2 - data = list("donor"=null,"viruses"=null,"donor_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null) - reagent_state = LIQUID - color = "#AAAAAA77" - can_synth = FALSE - nutriment_factor = 0.5 * REAGENTS_METABOLISM - -/obj/effect/decal/cleanable/femcum - name = "female ejaculate" - desc = null - gender = PLURAL - density = 0 - layer = ABOVE_NORMAL_TURF_LAYER - icon = 'modular_citadel/icons/obj/genitals/effects.dmi' - icon_state = "fem1" - random_icon_states = list("fem1", "fem2", "fem3", "fem4") - blood_state = null - bloodiness = null - -/obj/effect/decal/cleanable/femcum/Initialize(mapload) - . = ..() - dir = GLOB.cardinals - add_blood_DNA(list("Non-human DNA" = "A+")) - -/obj/effect/decal/cleanable/femcum/replace_decal(obj/effect/decal/cleanable/femcum/F) - if(F.blood_DNA) - blood_DNA |= F.blood_DNA - return ..() - -/datum/reagent/consumable/femcum/reaction_turf(turf/T, reac_volume) - if(!istype(T)) - return - if(reac_volume < 10) - return - - var/obj/effect/decal/cleanable/femcum/S = locate() in T - if(!S) - S = new(T) - if(data["blood_DNA"]) - S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"])) - -//aphrodisiac & anaphrodisiac - -/datum/reagent/drug/aphrodisiac - name = "Crocin" - description = "Naturally found in the crocus and gardenia flowers, this drug acts as a natural and safe aphrodisiac." - taste_description = "strawberry roofies" - taste_mult = 2 //Hide the roofies in stronger flavors - color = "#FFADFF"//PINK, rgb(255, 173, 255) - can_synth = FALSE - -/datum/reagent/drug/aphrodisiac/on_mob_life(mob/living/M) - if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO)) - if((prob(min(current_cycle/2,5)))) - M.emote(pick("moan","blush")) - if(prob(min(current_cycle/4,10))) - var/aroused_message = pick("You feel frisky.", "You're having trouble suppressing your urges.", "You feel in the mood.") - to_chat(M, "[aroused_message]") - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/list/genits = H.adjust_arousal(current_cycle, aphro = TRUE) // redundant but should still be here - for(var/g in genits) - var/obj/item/organ/genital/G = g - to_chat(M, "[G.arousal_verb]!") - ..() - -/datum/reagent/drug/aphrodisiacplus - name = "Hexacrocin" - description = "Chemically condensed form of basic crocin. This aphrodisiac is extremely powerful and addictive in most animals.\ - Addiction withdrawals can cause brain damage and shortness of breath. Overdosage can lead to brain damage and a \ - permanent increase in libido (commonly referred to as 'bimbofication')." - taste_description = "liquid desire" - color = "#FF2BFF"//dark pink - addiction_threshold = 20 - overdose_threshold = 20 - can_synth = FALSE - -/datum/reagent/drug/aphrodisiacplus/on_mob_life(mob/living/M) - if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO)) - if(prob(5)) - if(prob(current_cycle)) - M.say(pick("Hnnnnngghh...", "Ohh...", "Mmnnn...")) - else - M.emote(pick("moan","blush")) - if(prob(5)) - var/aroused_message - if(current_cycle>25) - aroused_message = pick("You need to fuck someone!", "You're bursting with sexual tension!", "You can't get sex off your mind!") - else - aroused_message = pick("You feel a bit hot.", "You feel strong sexual urges.", "You feel in the mood.", "You're ready to go down on someone.") - to_chat(M, "[aroused_message]") - REMOVE_TRAIT(M,TRAIT_NEVERBONER,APHRO_TRAIT) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/list/genits = H.adjust_arousal(100, aphro = TRUE) // redundant but should still be here - for(var/g in genits) - var/obj/item/organ/genital/G = g - to_chat(M, "[G.arousal_verb]!") - ..() - -/datum/reagent/drug/aphrodisiacplus/addiction_act_stage2(mob/living/M) - if(prob(30)) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2) - ..() -/datum/reagent/drug/aphrodisiacplus/addiction_act_stage3(mob/living/M) - if(prob(30)) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3) - - ..() -/datum/reagent/drug/aphrodisiacplus/addiction_act_stage4(mob/living/M) - if(prob(30)) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 4) - ..() - -/datum/reagent/drug/aphrodisiacplus/overdose_process(mob/living/M) - if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(33)) - if(prob(5) && ishuman(M) && M.has_dna() && (M.client?.prefs.cit_toggles & BIMBOFICATION)) - if(!HAS_TRAIT(M,TRAIT_PERMABONER)) - to_chat(M, "Your libido is going haywire!") - ADD_TRAIT(M,TRAIT_PERMABONER,APHRO_TRAIT) - ..() - -/datum/reagent/drug/anaphrodisiac - name = "Camphor" - description = "Naturally found in some species of evergreen trees, camphor is a waxy substance. When injested by most animals, it acts as an anaphrodisiac\ - , reducing libido and calming them. Non-habit forming and not addictive." - taste_description = "dull bitterness" - taste_mult = 2 - color = "#D9D9D9"//rgb(217, 217, 217) - reagent_state = SOLID - can_synth = FALSE - -/datum/reagent/drug/anaphrodisiac/on_mob_life(mob/living/M) - if(M && M.client?.prefs.arousable && prob(16)) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/list/genits = H.adjust_arousal(-100, aphro = TRUE) - if(genits.len) - to_chat(M, "You no longer feel aroused.") - ..() - -/datum/reagent/drug/anaphrodisiacplus - name = "Hexacamphor" - description = "Chemically condensed camphor. Causes an extreme reduction in libido and a permanent one if overdosed. Non-addictive." - taste_description = "tranquil celibacy" - color = "#D9D9D9"//rgb(217, 217, 217) - reagent_state = SOLID - overdose_threshold = 20 - can_synth = FALSE - -/datum/reagent/drug/anaphrodisiacplus/on_mob_life(mob/living/M) - if(M && M.client?.prefs.arousable) - REMOVE_TRAIT(M,TRAIT_PERMABONER,APHRO_TRAIT) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/list/genits = H.adjust_arousal(-100, aphro = TRUE) - if(genits.len) - to_chat(M, "You no longer feel aroused.") - - ..() - -/datum/reagent/drug/anaphrodisiacplus/overdose_process(mob/living/M) - if(M && M.client?.prefs.arousable && prob(5)) - to_chat(M, "You feel like you'll never feel aroused again...") - ADD_TRAIT(M,TRAIT_NEVERBONER,APHRO_TRAIT) - ..() - -//recipes -/datum/chemical_reaction/aphro - name = "crocin" - id = /datum/reagent/drug/aphrodisiac - results = list(/datum/reagent/drug/aphrodisiac = 6) - required_reagents = list(/datum/reagent/carbon = 2, /datum/reagent/hydrogen = 2, /datum/reagent/oxygen = 2, /datum/reagent/water = 1) - required_temp = 400 - mix_message = "The mixture boils off a pink vapor..."//The water boils off, leaving the crocin - -/datum/chemical_reaction/aphroplus - name = "hexacrocin" - id = /datum/reagent/drug/aphrodisiacplus - results = list(/datum/reagent/drug/aphrodisiacplus = 1) - required_reagents = list(/datum/reagent/drug/aphrodisiac = 6, /datum/reagent/phenol = 1) - required_temp = 400 - mix_message = "The mixture rapidly condenses and darkens in color..." - -/datum/chemical_reaction/anaphro - name = "camphor" - id = /datum/reagent/drug/anaphrodisiac - results = list(/datum/reagent/drug/anaphrodisiac = 6) - required_reagents = list(/datum/reagent/carbon = 2, /datum/reagent/hydrogen = 2, /datum/reagent/oxygen = 2, /datum/reagent/sulfur = 1) - required_temp = 400 - mix_message = "The mixture boils off a yellow, smelly vapor..."//Sulfur burns off, leaving the camphor - -/datum/chemical_reaction/anaphroplus - name = "pentacamphor" - id = /datum/reagent/drug/anaphrodisiacplus - results = list(/datum/reagent/drug/anaphrodisiacplus = 1) - required_reagents = list(/datum/reagent/drug/aphrodisiac = 5, /datum/reagent/acetone = 1) - required_temp = 300 - mix_message = "The mixture thickens and heats up slighty..." diff --git a/modular_citadel/icons/mob/inhands/stunsword_left.dmi b/modular_citadel/icons/mob/inhands/stunsword_left.dmi index 0ecc02d31a..02dfe2b915 100644 Binary files a/modular_citadel/icons/mob/inhands/stunsword_left.dmi and b/modular_citadel/icons/mob/inhands/stunsword_left.dmi differ diff --git a/modular_citadel/icons/mob/inhands/stunsword_right.dmi b/modular_citadel/icons/mob/inhands/stunsword_right.dmi index 76fa4d57c9..50e76d660b 100644 Binary files a/modular_citadel/icons/mob/inhands/stunsword_right.dmi and b/modular_citadel/icons/mob/inhands/stunsword_right.dmi differ diff --git a/modular_citadel/icons/mob/mam_tails.dmi b/modular_citadel/icons/mob/mam_tails.dmi index d91f15a3f7..a67c1b718c 100644 Binary files a/modular_citadel/icons/mob/mam_tails.dmi and b/modular_citadel/icons/mob/mam_tails.dmi differ diff --git a/modular_citadel/icons/mob/mam_taur.dmi b/modular_citadel/icons/mob/mam_taur.dmi index 3625c293c9..cf332019af 100644 Binary files a/modular_citadel/icons/mob/mam_taur.dmi and b/modular_citadel/icons/mob/mam_taur.dmi differ diff --git a/modular_citadel/icons/obj/food/food.dmi b/modular_citadel/icons/obj/food/food.dmi deleted file mode 100644 index da9a6c365f..0000000000 Binary files a/modular_citadel/icons/obj/food/food.dmi and /dev/null differ diff --git a/modular_citadel/icons/obj/items_and_weapons.dmi b/modular_citadel/icons/obj/items_and_weapons.dmi deleted file mode 100644 index 3b1d894d96..0000000000 Binary files a/modular_citadel/icons/obj/items_and_weapons.dmi and /dev/null differ diff --git a/modular_citadel/icons/obj/objects.dmi b/modular_citadel/icons/obj/objects.dmi deleted file mode 100644 index 55a6867303..0000000000 Binary files a/modular_citadel/icons/obj/objects.dmi and /dev/null differ diff --git a/modular_citadel/icons/obj/stunsword.dmi b/modular_citadel/icons/obj/stunsword.dmi deleted file mode 100644 index bfe4b45cd9..0000000000 Binary files a/modular_citadel/icons/obj/stunsword.dmi and /dev/null differ diff --git a/modular_citadel/icons/ui/screen_midnight.dmi b/modular_citadel/icons/ui/screen_midnight.dmi index a730c591ba..fc446a411c 100644 Binary files a/modular_citadel/icons/ui/screen_midnight.dmi and b/modular_citadel/icons/ui/screen_midnight.dmi differ diff --git a/modular_citadel/icons/ui/screen_operative.dmi b/modular_citadel/icons/ui/screen_operative.dmi index cb08f08ceb..9383b94718 100644 Binary files a/modular_citadel/icons/ui/screen_operative.dmi and b/modular_citadel/icons/ui/screen_operative.dmi differ diff --git a/modular_citadel/icons/ui/screen_plasmafire.dmi b/modular_citadel/icons/ui/screen_plasmafire.dmi index 5f8cd9d93c..97e577c7bd 100644 Binary files a/modular_citadel/icons/ui/screen_plasmafire.dmi and b/modular_citadel/icons/ui/screen_plasmafire.dmi differ diff --git a/modular_citadel/icons/ui/screen_slimecore.dmi b/modular_citadel/icons/ui/screen_slimecore.dmi index f2f0c88782..8f45ff3f76 100644 Binary files a/modular_citadel/icons/ui/screen_slimecore.dmi and b/modular_citadel/icons/ui/screen_slimecore.dmi differ diff --git a/modular_citadel/interface/skin.dmf b/modular_citadel/interface/skin.dmf deleted file mode 100644 index ec9a010128..0000000000 --- a/modular_citadel/interface/skin.dmf +++ /dev/null @@ -1,319 +0,0 @@ -macro "default" - - -menu "menu" - elem - name = "&File" - command = "" - saved-params = "is-checked" - elem - name = "&Quick screenshot\tF2" - command = ".screenshot auto" - category = "&File" - saved-params = "is-checked" - elem - name = "&Save screenshot as...\tShift+F2" - command = ".screenshot" - category = "&File" - saved-params = "is-checked" - elem - name = "" - command = "" - category = "&File" - saved-params = "is-checked" - elem "reconnectbutton" - name = "&Reconnect" - command = ".reconnect" - category = "&File" - saved-params = "is-checked" - elem - name = "&Quit\tAlt-F4" - command = ".quit" - category = "&File" - saved-params = "is-checked" - elem - name = "&Help" - command = "" - saved-params = "is-checked" - elem - name = "&Admin Help\tF1" - command = "adminhelp" - category = "&Help" - saved-params = "is-checked" - elem - name = "&Hotkeys" - command = "hotkeys-help" - category = "&Help" - saved-params = "is-checked" - - -window "mainwindow" - elem "mainwindow" - type = MAIN - pos = 0,0 - size = 640x440 - anchor1 = none - anchor2 = none - background-color = #242424 - is-default = true - saved-params = "pos;size;is-minimized;is-maximized" - icon = 'icons\\ss13_64.png' - macro = "default" - menu = "menu" - elem "split" - type = CHILD - pos = 0,0 - size = 637x440 - anchor1 = 0,0 - anchor2 = 100,100 - background-color = #272727 - saved-params = "splitter" - left = "mapwindow" - right = "infowindow" - is-vert = true - splitter = 75 - elem "asset_cache_browser" - type = BROWSER - pos = 0,0 - size = 200x200 - anchor1 = none - anchor2 = none - background-color = #272727 - is-visible = false - saved-params = "" - elem "tooltip" - type = BROWSER - pos = 0,0 - size = 999x999 - anchor1 = none - anchor2 = none - background-color = #272727 - is-visible = false - saved-params = "" - -window "mapwindow" - elem "mapwindow" - type = MAIN - pos = 418,0 - size = 1024x1024 - anchor1 = none - anchor2 = none - background-color = none - saved-params = "pos;size;is-minimized;is-maximized" - statusbar = false - is-pane = true - outer-size = 684x617 - inner-size = 662x561 - elem "map" - type = MAP - pos = 0,0 - size = 1024x1024 - anchor1 = 0,0 - anchor2 = 100,100 - font-family = "Arial" - font-size = 7 - is-default = true - saved-params = "icon-size" - zoom-mode = distort - style = ".center { text-align: center; }\n.maptext { font-family: 'Small Fonts'; font-size: 7px; -dm-text-outline: 1px black; color: white; line-height: 1.1; }\n.command_headset { font-weight: bold;\tfont-size: 8px; } .small { font-size: 6px; }\n.big { font-size: 8px; }\n.reallybig { font-size: 8px; }\n.extremelybig { font-size: 8px; }\n.greentext { color: #00ff00; font-size: 7px; }\n.redtext { color: #ff0000; font-size: 7px; }\n.clown { color: #ff69bf; font-size: 7px; font-weight: bold; }\n.his_grace { color: #15d512; }\n.hypnophrase { color: #0d0d0d; font-weight: bold; }\n.yell { font-weight: bold; }\n.italics { font-size: 6px; }" - -window "infowindow" - elem "infowindow" - type = MAIN - pos = 0,0 - size = 640x480 - anchor1 = none - anchor2 = none - background-color = #242424 - saved-params = "pos;size;is-minimized;is-maximized" - is-pane = true - elem "info" - type = CHILD - pos = 0,30 - size = 640x445 - anchor1 = 0,0 - anchor2 = 100,100 - background-color = #272727 - saved-params = "splitter" - left = "statwindow" - right = "outputwindow" - is-vert = false - elem "changelog" - type = BUTTON - pos = 16,5 - size = 104x20 - anchor1 = 3,0 - anchor2 = 19,0 - text-color = #e0e0e0 - background-color = #40628a - saved-params = "is-checked" - text = "Changelog" - command = "changelog" - elem "rules" - type = BUTTON - pos = 120,5 - size = 100x20 - anchor1 = 19,0 - anchor2 = 34,0 - text-color = #e0e0e0 - background-color = #40628a - saved-params = "is-checked" - text = "Rules" - command = "rules" - elem "wiki" - type = BUTTON - pos = 220,5 - size = 100x20 - anchor1 = 34,0 - anchor2 = 50,0 - text-color = #e0e0e0 - background-color = #40628a - saved-params = "is-checked" - text = "Wiki" - command = "wiki" - elem "forum" - type = BUTTON - pos = 320,5 - size = 100x20 - anchor1 = 50,0 - anchor2 = 66,0 - text-color = #e0e0e0 - background-color = #40628a - saved-params = "is-checked" - text = "Forum" - command = "forum" - elem "github" - type = BUTTON - pos = 420,5 - size = 100x20 - anchor1 = 66,0 - anchor2 = 81,0 - text-color = #e0e0e0 - background-color = #40628a - saved-params = "is-checked" - text = "GitHub" - command = "github" - elem "report-issue" - type = BUTTON - pos = 520,5 - size = 100x20 - anchor1 = 81,0 - anchor2 = 97,0 - font-size = 8 - text-color = #e0e0e0 - background-color = #a92c2c - saved-params = "is-checked" - text = "Report Issue" - command = "report-issue" - -window "outputwindow" - elem "outputwindow" - type = MAIN - pos = 0,0 - size = 640x480 - anchor1 = none - anchor2 = none - background-color = #272727 - saved-params = "pos;size;is-minimized;is-maximized" - titlebar = false - statusbar = false - can-close = false - can-minimize = false - can-resize = false - is-pane = true - elem "input" - type = INPUT - pos = 2,460 - size = 595x20 - anchor1 = 0,100 - anchor2 = 100,100 - background-color = #d3b5b5 - is-default = true - border = sunken - saved-params = "command" - elem "say" - type = BUTTON - pos = 600,460 - size = 37x20 - anchor1 = 100,100 - anchor2 = none - text-color = #e0e0e0 - background-color = #272727 - saved-params = "is-checked" - text = "Chat" - command = ".winset \"say.is-checked=true ? input.command=\"!say \\\"\" : input.command=\"" - is-flat = true - button-type = pushbox - elem "browseroutput" - type = BROWSER - pos = 0,0 - size = 640x456 - anchor1 = 0,0 - anchor2 = 100,100 - background-color = #272727 - is-visible = false - is-disabled = true - saved-params = "" - auto-format = false - elem "output" - type = OUTPUT - pos = 0,0 - size = 640x456 - anchor1 = 0,0 - anchor2 = 100,100 - text-color = #e0e0e0 - background-color = #272727 - is-default = true - saved-params = "" - -window "statwindow" - elem "statwindow" - type = MAIN - pos = 281,0 - size = 640x480 - anchor1 = none - anchor2 = none - background-color = #242424 - saved-params = "pos;size;is-minimized;is-maximized" - is-pane = true - elem "stat" - type = INFO - pos = 0,0 - size = 640x480 - anchor1 = 0,0 - anchor2 = 100,100 - text-color = #e0e0e0 - background-color = #272727 - is-default = true - saved-params = "" - tab-text-color = #e0e0e0 - tab-background-color = #242424 - prefix-color = #e0e0e0 - suffix-color = #e0e0e0 - -window "preferences_window" - elem "preferences_window" - type = MAIN - pos = 372,0 - size = 1280x1000 - anchor1 = none - anchor2 = none - is-visible = false - saved-params = "pos;size;is-minimized;is-maximized" - statusbar = false - elem "preferences_browser" - type = BROWSER - pos = 0,0 - size = 960x1000 - anchor1 = 0,0 - anchor2 = 75,100 - saved-params = "" - elem "character_preview_map" - type = MAP - pos = 960,0 - size = 320x1000 - anchor1 = 75,0 - anchor2 = 100,100 - right-click = true - saved-params = "zoom;letterbox;zoom-mode" - diff --git a/rust_g.dll b/rust_g.dll index 27ee495684..f4be6e730a 100644 Binary files a/rust_g.dll and b/rust_g.dll differ diff --git a/sound/items/dump_it.ogg b/sound/items/dump_it.ogg new file mode 100644 index 0000000000..33bdb49e69 Binary files /dev/null and b/sound/items/dump_it.ogg differ diff --git a/strings/tips.txt b/strings/tips.txt index c8f233bb1a..b135692778 100644 --- a/strings/tips.txt +++ b/strings/tips.txt @@ -37,6 +37,7 @@ As a Medical Doctor, treating plasmamen is not impossible! Salbutamol stops them As a Medical Doctor, you can point your penlight at people to create a medical hologram. This lets them know that you're coming to treat them. As a Medical Doctor, you can extract implants by holding an empty implant case in your offhand while performing the extraction step. As a Medical Doctor, clone scanning people will implant them with a health tracker that displays their vitals in the clone records. Useful to check on crew members that didn't activate suit sensors! +As a Medical Doctor, medical gauze stops bleeding as well as heals 5 brute damage, this even works on the dead! Make sure to always have some gauze on you to stop bleeding before dragging someone. As a Chemist, there are dozens of chemicals that can heal, and even more that can cause harm. Experiment! As a Chemist, some chemicals can only be synthesized by heating up the contents in the chemical heater. As a Chemist, you will be expected to supply crew with certain chemicals. For example, clonexadone and mannitol for the cryo tubes, unstable mutagen and saltpetre for botany as well as healing pills and patches for the front desk. @@ -64,6 +65,7 @@ As a Roboticist, you can greatly help out Shaft Miners by building a Firefighter As a Roboticist, you can augment people with cyborg limbs. Augmented limbs can easily be repaired with cables and welders. As a Roboticist, you can use your printer that is linked to the ore silo to teleport mats into your work place! As a Roboticist, you can upgrade cleanbots with adv mops and brooms to make them faster and better! +As a Roboticist, you can upgrade medical bots with diamond-tipped syringes, MK.II Hypospray, dispenser-sleeper-chemheater boards to make them inject faster, harder and better chems! As the AI, you can click on people's names to look at them. This only works if there are cameras that can see them. As the AI, you can quickly open and close doors by holding shift while clicking them, bolt them when holding ctrl, and even shock them while holding alt. As the AI, you can take pictures with your camera and upload them to newscasters. @@ -263,7 +265,12 @@ As a Devil, as long as you control at least one other soul, you will automatical At which time a Devil's nameth is spake on the tongue of man, the Devil may appeareth. You can swap floor tiles by holding a crowbar in one hand and a stack of tiles in the other. When hacking doors, cutting and mending the "test light wire" will restore power to the door. +When hacking, remote singulars pluse when attached to a wire and pinged. This can allow you to hack things or set traps from far away. When crafting most items, you can either manually combine parts or use the crafting menu. Suit storage units not only remove blood and dirt from clothing, but also radiation! Remote devices will work when used through cameras. For example: Bluespace RPEDs and door remotes. Laser pointers can be upgraded by replacing its micro laser with a better one from RnD! Use a screwdriver on it to remove the old laser. Upgrading the laser pointer gives you better odds of stunning a cyborg, and even blinding people with sunglasses. +Being out of combat mode makes makes you deal less damage to people and objects when attacking. +Resting makes you deal less damage to people and objects when attacking. +You do not regenerate as much stamina while in combat mode. Resting (being on the ground) makes you regenerate stamina faster. +Remember to be in combat mode while in combat, as otherwise you will be penalized by taking more incoming damage and dealing less damage to your adversary. diff --git a/tgstation.dme b/tgstation.dme index c727155ba2..b76537b8da 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -44,6 +44,7 @@ #include "code\__DEFINES\donator_groupings.dm" #include "code\__DEFINES\dye_keys.dm" #include "code\__DEFINES\dynamic.dm" +#include "code\__DEFINES\economy.dm" #include "code\__DEFINES\events.dm" #include "code\__DEFINES\exports.dm" #include "code\__DEFINES\fantasy_affixes.dm" @@ -91,7 +92,6 @@ #include "code\__DEFINES\research.dm" #include "code\__DEFINES\robots.dm" #include "code\__DEFINES\role_preferences.dm" -#include "code\__DEFINES\rust_g.config.dm" #include "code\__DEFINES\rust_g.dm" #include "code\__DEFINES\say.dm" #include "code\__DEFINES\security_levels.dm" @@ -102,7 +102,6 @@ #include "code\__DEFINES\stat.dm" #include "code\__DEFINES\stat_tracking.dm" #include "code\__DEFINES\status_effects.dm" -#include "code\__DEFINES\storage.dm" #include "code\__DEFINES\subsystems.dm" #include "code\__DEFINES\tgs.config.dm" #include "code\__DEFINES\tgs.dm" @@ -123,6 +122,7 @@ #include "code\__DEFINES\_flags\obj_flags.dm" #include "code\__DEFINES\combat\block.dm" #include "code\__DEFINES\combat\block_parry.dm" +#include "code\__DEFINES\admin\keybindings.dm" #include "code\__DEFINES\dcs\flags.dm" #include "code\__DEFINES\dcs\helpers.dm" #include "code\__DEFINES\dcs\signals.dm" @@ -133,11 +133,15 @@ #include "code\__DEFINES\misc\return_values.dm" #include "code\__DEFINES\mobs\slowdowns.dm" #include "code\__DEFINES\research\stock_parts.dm" -#include "code\__DEFINES\skills\skills.dm" +#include "code\__DEFINES\skills\defines.dm" +#include "code\__DEFINES\skills\helpers.dm" +#include "code\__DEFINES\storage\_storage.dm" +#include "code\__DEFINES\storage\volumetrics.dm" #include "code\__HELPERS\_cit_helpers.dm" #include "code\__HELPERS\_lists.dm" #include "code\__HELPERS\_logging.dm" #include "code\__HELPERS\_string_lists.dm" +#include "code\__HELPERS\angles.dm" #include "code\__HELPERS\areas.dm" #include "code\__HELPERS\AStar.dm" #include "code\__HELPERS\cmp.dm" @@ -188,7 +192,9 @@ #include "code\_globalvars\misc.dm" #include "code\_globalvars\regexes.dm" #include "code\_globalvars\traits.dm" +#include "code\_globalvars\lists\client.dm" #include "code\_globalvars\lists\flavor_misc.dm" +#include "code\_globalvars\lists\keybindings.dm" #include "code\_globalvars\lists\maintenance_loot.dm" #include "code\_globalvars\lists\mapping.dm" #include "code\_globalvars\lists\medals.dm" @@ -273,6 +279,7 @@ #include "code\controllers\subsystem\dbcore.dm" #include "code\controllers\subsystem\dcs.dm" #include "code\controllers\subsystem\disease.dm" +#include "code\controllers\subsystem\economy.dm" #include "code\controllers\subsystem\events.dm" #include "code\controllers\subsystem\fail2topic.dm" #include "code\controllers\subsystem\fire_burning.dm" @@ -293,7 +300,6 @@ #include "code\controllers\subsystem\minimaps.dm" #include "code\controllers\subsystem\minor_mapping.dm" #include "code\controllers\subsystem\mobs.dm" -#include "code\controllers\subsystem\moods.dm" #include "code\controllers\subsystem\nightshift.dm" #include "code\controllers\subsystem\npcpool.dm" #include "code\controllers\subsystem\overlays.dm" @@ -371,6 +377,7 @@ #include "code\datums\shuttles.dm" #include "code\datums\soullink.dm" #include "code\datums\spawners_menu.dm" +#include "code\datums\tgs_event_handler.dm" #include "code\datums\verbs.dm" #include "code\datums\weakrefs.dm" #include "code\datums\world_topic.dm" @@ -387,6 +394,7 @@ #include "code\datums\components\_component.dm" #include "code\datums\components\anti_magic.dm" #include "code\datums\components\armor_plate.dm" +#include "code\datums\components\art.dm" #include "code\datums\components\bane.dm" #include "code\datums\components\bouncy.dm" #include "code\datums\components\butchering.dm" @@ -397,10 +405,9 @@ #include "code\datums\components\dejavu.dm" #include "code\datums\components\earprotection.dm" #include "code\datums\components\edit_complainer.dm" -#include "code\datums\components\empprotection.dm" #include "code\datums\components\explodable.dm" +#include "code\datums\components\field_of_vision.dm" #include "code\datums\components\footstep.dm" -#include "code\datums\components\forced_gravity.dm" #include "code\datums\components\identification.dm" #include "code\datums\components\igniter.dm" #include "code\datums\components\infective.dm" @@ -435,7 +442,6 @@ #include "code\datums\components\summoning.dm" #include "code\datums\components\swarming.dm" #include "code\datums\components\tackle.dm" -#include "code\datums\components\tactical.dm" #include "code\datums\components\thermite.dm" #include "code\datums\components\uplink.dm" #include "code\datums\components\virtual_reality.dm" @@ -525,9 +531,12 @@ #include "code\datums\elements\cleaning.dm" #include "code\datums\elements\dusts_on_catatonia.dm" #include "code\datums\elements\dusts_on_leaving_area.dm" +#include "code\datums\elements\dwarfism.dm" #include "code\datums\elements\earhealing.dm" +#include "code\datums\elements\empprotection.dm" #include "code\datums\elements\firestacker.dm" #include "code\datums\elements\flavor_text.dm" +#include "code\datums\elements\forced_gravity.dm" #include "code\datums\elements\ghost_role_eligibility.dm" #include "code\datums\elements\mob_holder.dm" #include "code\datums\elements\polychromic.dm" @@ -537,6 +546,7 @@ #include "code\datums\elements\squish.dm" #include "code\datums\elements\swimming.dm" #include "code\datums\elements\sword_point.dm" +#include "code\datums\elements\tactical.dm" #include "code\datums\elements\update_icon_blocker.dm" #include "code\datums\elements\update_icon_updates_onmob.dm" #include "code\datums\elements\wuv.dm" @@ -587,7 +597,12 @@ #include "code\datums\skills\_check_skills.dm" #include "code\datums\skills\_skill.dm" #include "code\datums\skills\_skill_holder.dm" +#include "code\datums\skills\_skill_modifier.dm" +#include "code\datums\skills\engineering.dm" #include "code\datums\skills\medical.dm" +#include "code\datums\skills\modifiers\job.dm" +#include "code\datums\skills\modifiers\mood.dm" +#include "code\datums\skills\modifiers\organs.dm" #include "code\datums\status_effects\buffs.dm" #include "code\datums\status_effects\debuffs.dm" #include "code\datums\status_effects\gas.dm" @@ -722,6 +737,7 @@ #include "code\game\machinery\gulag_teleporter.dm" #include "code\game\machinery\harvester.dm" #include "code\game\machinery\hologram.dm" +#include "code\game\machinery\hypnochair.dm" #include "code\game\machinery\igniter.dm" #include "code\game\machinery\iv_drip.dm" #include "code\game\machinery\launch_pad.dm" @@ -932,7 +948,9 @@ #include "code\game\objects\items\control_wand.dm" #include "code\game\objects\items\cosmetics.dm" #include "code\game\objects\items\courtroom.dm" +#include "code\game\objects\items\crab17.dm" #include "code\game\objects\items\crayons.dm" +#include "code\game\objects\items\credit_holochip.dm" #include "code\game\objects\items\debug_items.dm" #include "code\game\objects\items\defib.dm" #include "code\game\objects\items\dehy_carp.dm" @@ -1010,6 +1028,7 @@ #include "code\game\objects\items\devices\multitool.dm" #include "code\game\objects\items\devices\paicard.dm" #include "code\game\objects\items\devices\pipe_painter.dm" +#include "code\game\objects\items\devices\polycircuit.dm" #include "code\game\objects\items\devices\powersink.dm" #include "code\game\objects\items\devices\pressureplates.dm" #include "code\game\objects\items\devices\quantum_keycard.dm" @@ -1084,6 +1103,7 @@ #include "code\game\objects\items\stacks\tiles\light.dm" #include "code\game\objects\items\stacks\tiles\tile_mineral.dm" #include "code\game\objects\items\stacks\tiles\tile_types.dm" +#include "code\game\objects\items\storage\_storage.dm" #include "code\game\objects\items\storage\backpack.dm" #include "code\game\objects\items\storage\bags.dm" #include "code\game\objects\items\storage\belt.dm" @@ -1095,7 +1115,6 @@ #include "code\game\objects\items\storage\firstaid.dm" #include "code\game\objects\items\storage\lockbox.dm" #include "code\game\objects\items\storage\secure.dm" -#include "code\game\objects\items\storage\storage.dm" #include "code\game\objects\items\storage\toolbox.dm" #include "code\game\objects\items\storage\uplink_kits.dm" #include "code\game\objects\items\storage\wallets.dm" @@ -1463,6 +1482,7 @@ #include "code\modules\antagonists\clockcult\clock_items\soul_vessel.dm" #include "code\modules\antagonists\clockcult\clock_items\wraith_spectacles.dm" #include "code\modules\antagonists\clockcult\clock_items\clock_weapons\_call_weapon.dm" +#include "code\modules\antagonists\clockcult\clock_items\clock_weapons\ratvarian_shield.dm" #include "code\modules\antagonists\clockcult\clock_items\clock_weapons\ratvarian_spear.dm" #include "code\modules\antagonists\clockcult\clock_mobs\_eminence.dm" #include "code\modules\antagonists\clockcult\clock_mobs\clockwork_marauder.dm" @@ -1566,6 +1586,15 @@ #include "code\modules\antagonists\wizard\equipment\soulstone.dm" #include "code\modules\antagonists\wizard\equipment\spellbook.dm" #include "code\modules\antagonists\xeno\xeno.dm" +#include "code\modules\arousal\arousal.dm" +#include "code\modules\arousal\genitals.dm" +#include "code\modules\arousal\genitals_sprite_accessories.dm" +#include "code\modules\arousal\organs\breasts.dm" +#include "code\modules\arousal\organs\penis.dm" +#include "code\modules\arousal\organs\testicles.dm" +#include "code\modules\arousal\organs\vagina.dm" +#include "code\modules\arousal\organs\womb.dm" +#include "code\modules\arousal\toys\dildos.dm" #include "code\modules\assembly\assembly.dm" #include "code\modules\assembly\bomb.dm" #include "code\modules\assembly\doorcontrol.dm" @@ -1832,6 +1861,9 @@ #include "code\modules\detectivework\detective_work.dm" #include "code\modules\detectivework\evidence.dm" #include "code\modules\detectivework\scanner.dm" +#include "code\modules\economy\_economy.dm" +#include "code\modules\economy\account.dm" +#include "code\modules\economy\paystand.dm" #include "code\modules\emoji\emoji_parse.dm" #include "code\modules\error_handler\error_handler.dm" #include "code\modules\error_handler\error_viewer.dm" @@ -2014,6 +2046,7 @@ #include "code\modules\hydroponics\grown\onion.dm" #include "code\modules\hydroponics\grown\peach.dm" #include "code\modules\hydroponics\grown\peanuts.dm" +#include "code\modules\hydroponics\grown\peas.dm" #include "code\modules\hydroponics\grown\pineapple.dm" #include "code\modules\hydroponics\grown\potato.dm" #include "code\modules\hydroponics\grown\pumpkin.dm" @@ -2119,16 +2152,22 @@ #include "code\modules\jobs\job_types\virologist.dm" #include "code\modules\jobs\job_types\warden.dm" #include "code\modules\jobs\map_changes\map_changes.dm" -#include "code\modules\keybindings\bindings_admin.dm" #include "code\modules\keybindings\bindings_atom.dm" -#include "code\modules\keybindings\bindings_carbon.dm" #include "code\modules\keybindings\bindings_client.dm" -#include "code\modules\keybindings\bindings_human.dm" -#include "code\modules\keybindings\bindings_living.dm" -#include "code\modules\keybindings\bindings_mob.dm" -#include "code\modules\keybindings\bindings_robot.dm" #include "code\modules\keybindings\focus.dm" #include "code\modules\keybindings\setup.dm" +#include "code\modules\keybindings\keybind\__defines.dm" +#include "code\modules\keybindings\keybind\_keybind.dm" +#include "code\modules\keybindings\keybind\admin.dm" +#include "code\modules\keybindings\keybind\carbon.dm" +#include "code\modules\keybindings\keybind\client.dm" +#include "code\modules\keybindings\keybind\emote.dm" +#include "code\modules\keybindings\keybind\human.dm" +#include "code\modules\keybindings\keybind\living.dm" +#include "code\modules\keybindings\keybind\mob.dm" +#include "code\modules\keybindings\keybind\movement.dm" +#include "code\modules\keybindings\keybind\robot.dm" +#include "code\modules\keybindings\keybind\targeting.dm" #include "code\modules\language\aphasia.dm" #include "code\modules\language\beachbum.dm" #include "code\modules\language\codespeak.dm" @@ -2146,6 +2185,7 @@ #include "code\modules\language\ratvarian.dm" #include "code\modules\language\slime.dm" #include "code\modules\language\swarmer.dm" +#include "code\modules\language\sylvan.dm" #include "code\modules\language\vampiric.dm" #include "code\modules\language\xenocommon.dm" #include "code\modules\library\lib_codex_gigas.dm" @@ -2229,6 +2269,7 @@ #include "code\modules\mob\say_vr.dm" #include "code\modules\mob\status_procs.dm" #include "code\modules\mob\transform_procs.dm" +#include "code\modules\mob\typing_indicator.dm" #include "code\modules\mob\update_icons.dm" #include "code\modules\mob\camera\camera.dm" #include "code\modules\mob\dead\dead.dm" @@ -2359,10 +2400,12 @@ #include "code\modules\mob\living\carbon\human\human_movement.dm" #include "code\modules\mob\living\carbon\human\inventory.dm" #include "code\modules\mob\living\carbon\human\life.dm" +#include "code\modules\mob\living\carbon\human\login.dm" #include "code\modules\mob\living\carbon\human\physiology.dm" #include "code\modules\mob\living\carbon\human\say.dm" #include "code\modules\mob\living\carbon\human\species.dm" #include "code\modules\mob\living\carbon\human\status_procs.dm" +#include "code\modules\mob\living\carbon\human\typing_indicator.dm" #include "code\modules\mob\living\carbon\human\update_icons.dm" #include "code\modules\mob\living\carbon\human\species_types\abductors.dm" #include "code\modules\mob\living\carbon\human\species_types\android.dm" @@ -2438,6 +2481,7 @@ #include "code\modules\mob\living\silicon\robot\login.dm" #include "code\modules\mob\living\silicon\robot\robot.dm" #include "code\modules\mob\living\silicon\robot\robot_defense.dm" +#include "code\modules\mob\living\silicon\robot\robot_defines.dm" #include "code\modules\mob\living\silicon\robot\robot_mobility.dm" #include "code\modules\mob\living\silicon\robot\robot_modules.dm" #include "code\modules\mob\living\silicon\robot\robot_movement.dm" @@ -2918,6 +2962,7 @@ #include "code\modules\reagents\reagent_containers\glass.dm" #include "code\modules\reagents\reagent_containers\hypospray.dm" #include "code\modules\reagents\reagent_containers\hypovial.dm" +#include "code\modules\reagents\reagent_containers\maunamug.dm" #include "code\modules\reagents\reagent_containers\medspray.dm" #include "code\modules\reagents\reagent_containers\patch.dm" #include "code\modules\reagents\reagent_containers\pill.dm" @@ -2935,6 +2980,7 @@ #include "code\modules\recycling\disposal\outlet.dm" #include "code\modules\recycling\disposal\pipe.dm" #include "code\modules\recycling\disposal\pipe_sorting.dm" +#include "code\modules\research\bepis.dm" #include "code\modules\research\designs.dm" #include "code\modules\research\destructive_analyzer.dm" #include "code\modules\research\experimentor.dm" @@ -3016,7 +3062,21 @@ #include "code\modules\research\techweb\__techweb_helpers.dm" #include "code\modules\research\techweb\_techweb.dm" #include "code\modules\research\techweb\_techweb_node.dm" -#include "code\modules\research\techweb\all_nodes.dm" +#include "code\modules\research\techweb\nodes\alien_nodes.dm" +#include "code\modules\research\techweb\nodes\bepis_nodes.dm" +#include "code\modules\research\techweb\nodes\biotech_nodes.dm" +#include "code\modules\research\techweb\nodes\bluespace_nodes.dm" +#include "code\modules\research\techweb\nodes\computer_hud_nodes.dm" +#include "code\modules\research\techweb\nodes\engineering_nodes.dm" +#include "code\modules\research\techweb\nodes\export_nodes.dm" +#include "code\modules\research\techweb\nodes\mecha_nodes.dm" +#include "code\modules\research\techweb\nodes\medical_nodes.dm" +#include "code\modules\research\techweb\nodes\misc_nodes.dm" +#include "code\modules\research\techweb\nodes\nanites_nodes.dm" +#include "code\modules\research\techweb\nodes\robotics_nodes.dm" +#include "code\modules\research\techweb\nodes\syndicate_nodes.dm" +#include "code\modules\research\techweb\nodes\tools_nodes.dm" +#include "code\modules\research\techweb\nodes\weaponry_nodes.dm" #include "code\modules\research\xenobiology\xenobio_camera.dm" #include "code\modules\research\xenobiology\xenobiology.dm" #include "code\modules\research\xenobiology\crossbreeding\__corecross.dm" @@ -3295,9 +3355,7 @@ #include "interface\interface.dm" #include "interface\menu.dm" #include "interface\stylesheet.dm" -#include "modular_citadel\code\__HELPERS\list2list.dm" -#include "modular_citadel\code\__HELPERS\lists.dm" -#include "modular_citadel\code\__HELPERS\mobs.dm" +#include "interface\skin.dmf" #include "modular_citadel\code\_onclick\click.dm" #include "modular_citadel\code\_onclick\item_attack.dm" #include "modular_citadel\code\_onclick\other_mobs.dm" @@ -3306,24 +3364,11 @@ #include "modular_citadel\code\_onclick\hud\stamina.dm" #include "modular_citadel\code\datums\components\souldeath.dm" #include "modular_citadel\code\datums\status_effects\chems.dm" -#include "modular_citadel\code\game\machinery\wishgranter.dm" #include "modular_citadel\code\game\objects\cit_screenshake.dm" #include "modular_citadel\code\game\objects\effects\temporary_visuals\souldeath.dm" -#include "modular_citadel\code\modules\admin\chat_commands.dm" #include "modular_citadel\code\modules\admin\holder2.dm" #include "modular_citadel\code\modules\admin\secrets.dm" -#include "modular_citadel\code\modules\arousal\arousal.dm" -#include "modular_citadel\code\modules\arousal\genitals.dm" -#include "modular_citadel\code\modules\arousal\genitals_sprite_accessories.dm" -#include "modular_citadel\code\modules\arousal\organs\breasts.dm" -#include "modular_citadel\code\modules\arousal\organs\penis.dm" -#include "modular_citadel\code\modules\arousal\organs\testicles.dm" -#include "modular_citadel\code\modules\arousal\organs\vagina.dm" -#include "modular_citadel\code\modules\arousal\organs\womb.dm" -#include "modular_citadel\code\modules\arousal\toys\dildos.dm" -#include "modular_citadel\code\modules\client\client_defines.dm" #include "modular_citadel\code\modules\client\client_procs.dm" -#include "modular_citadel\code\modules\client\preferences.dm" #include "modular_citadel\code\modules\client\preferences_savefile.dm" #include "modular_citadel\code\modules\client\preferences_toggles.dm" #include "modular_citadel\code\modules\client\loadout\__donator.dm" @@ -3348,7 +3393,6 @@ #include "modular_citadel\code\modules\custom_loadout\custom_items.dm" #include "modular_citadel\code\modules\custom_loadout\load_to_mob.dm" #include "modular_citadel\code\modules\custom_loadout\read_from_file.dm" -#include "modular_citadel\code\modules\language\sylvan.dm" #include "modular_citadel\code\modules\mentor\dementor.dm" #include "modular_citadel\code\modules\mentor\follow.dm" #include "modular_citadel\code\modules\mentor\mentor.dm" @@ -3366,7 +3410,6 @@ #include "modular_citadel\code\modules\mob\living\carbon\reindex_screams.dm" #include "modular_citadel\code\modules\mob\living\carbon\human\human.dm" #include "modular_citadel\code\modules\mob\living\carbon\human\human_defense.dm" -#include "modular_citadel\code\modules\mob\living\silicon\robot\dogborg_equipment.dm" #include "modular_citadel\code\modules\projectiles\gun.dm" #include "modular_citadel\code\modules\projectiles\ammunition\caseless.dm" #include "modular_citadel\code\modules\projectiles\ammunition\ballistic\smg\smg.dm" @@ -3391,6 +3434,4 @@ #include "modular_citadel\code\modules\reagents\chemistry\recipes\fermi.dm" #include "modular_citadel\code\modules\reagents\objects\clothes.dm" #include "modular_citadel\code\modules\reagents\objects\items.dm" -#include "modular_citadel\code\modules\reagents\reagents\cit_reagents.dm" -#include "modular_citadel\interface\skin.dmf" // END_INCLUDE diff --git a/tgui-next/packages/tgui/interfaces/Bepis.js b/tgui-next/packages/tgui/interfaces/Bepis.js index da23cb11aa..993af415dc 100644 --- a/tgui-next/packages/tgui/interfaces/Bepis.js +++ b/tgui-next/packages/tgui/interfaces/Bepis.js @@ -89,6 +89,9 @@ export const Bepis = props => { Average technology cost: {data.mean_value} + + Current chance of Success: Est. {data.success_estimate}% + {data.error_name && ( Previous Failure Reason: Deposited cash value too low. diff --git a/tgui-next/packages/tgui/interfaces/Canvas.js b/tgui-next/packages/tgui/interfaces/Canvas.js new file mode 100644 index 0000000000..b30639697c --- /dev/null +++ b/tgui-next/packages/tgui/interfaces/Canvas.js @@ -0,0 +1,96 @@ +import { Fragment } from 'inferno'; +import { useBackend } from '../backend'; +import { Box, Button } from '../components'; +import { Component, createRef } from 'inferno'; +import { pureComponentHooks } from 'common/react'; + + +class PaintCanvas extends Component { + constructor(props) { + super(props); + this.canvasRef = createRef(); + this.onCVClick = props.onCanvasClick; + } + + componentDidMount() { + this.drawCanvas(this.props); + } + + componentDidUpdate() { + this.drawCanvas(this.props); + } + + drawCanvas(propSource) { + const ctx = this.canvasRef.current.getContext("2d"); + const grid = propSource.value; + const x_size = grid.length; + if (!x_size) { + return; + } + const y_size = grid[0].length; + const x_scale = Math.round(this.canvasRef.current.width / x_size); + const y_scale = Math.round(this.canvasRef.current.height / y_size); + ctx.save(); + ctx.scale(x_scale, y_scale); + for (let x = 0; x < grid.length; x++) { + const element = grid[x]; + for (let y = 0; y < element.length; y++) { + const color = element[y]; + ctx.fillStyle = color; + ctx.fillRect(x, y, 1, 1); + } + } + ctx.restore(); + } + + clickwrapper(event) { + const x_size = this.props.value.length; + if (!x_size) + { + return; + } + const y_size = this.props.value[0].length; + const x_scale = this.canvasRef.current.width / x_size; + const y_scale = this.canvasRef.current.height / y_size; + const x = Math.floor(event.offsetX / x_scale)+1; + const y = Math.floor(event.offsetY / y_scale)+1; + this.onCVClick(x, y); + } + + render() { + const { + res = 1, + value, + px_per_unit = 28, + ...rest + } = this.props; + const x_size = value.length * px_per_unit; + const y_size = x_size !== 0 ? value[0].length * px_per_unit : 0; + return ( + this.clickwrapper(e)}> + Canvas failed to render. + + ); + } +} +export const Canvas = props => { + const { act, data } = useBackend(props); + return ( + + act("paint", { x, y })} /> + + {!data.finalized + && act("finalize")} + content="Finalize" />} + {data.name} + + ); +}; diff --git a/tgui-next/packages/tgui/interfaces/Cargo.js b/tgui-next/packages/tgui/interfaces/Cargo.js index 85ae19755e..133b1b00ab 100644 --- a/tgui-next/packages/tgui/interfaces/Cargo.js +++ b/tgui-next/packages/tgui/interfaces/Cargo.js @@ -75,7 +75,17 @@ export const Cargo = props => { {() => (
+ buttons={( + + {cartButtons} +
)} @@ -137,11 +147,6 @@ const Catalog = props => { {pack.name}: - - {!!pack.small_item && ( - Small Item - )} - {!!pack.access && ( Restrictions Apply @@ -149,6 +154,10 @@ const Catalog = props => {